说明 : 此模板是供loony复习用的,如有瑕疵误喷!!!
友情提示 : 次文章仅展示模板,没有讲解部分哦!
以下是正文:
int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
例题:
P2118 比例简化
P1372 又是毕业季I
int lcm(int a, int b) {
return a * b / gcd(a, b);
}
例题:
P1029 最大公约数和最小公倍数问题
memset(check,0,sizeof(check));
check[1]=ture;
for(int i=2;i<=n;i++){
if(!check[i]){
prime[++cnt]=i;
}
for(int j=1;j<=cnt;j++){
if(prime[j]*i>n){
break;
}
check[prime[j]*i]=ture;
if(i%prime[j]==0){
break;
}
}
}
例题:
P3383 线性筛素数
int is_prime(int n){
for(int i=2;i*i<=n;i++){
if(n%i==0){
return 0;
}
}
return 1;
}
例题:
AT1476 素数判定
P1217 回文质数
for(int i=2;i<=n;i++){
while(n!=1){
if(n%i==0){
printf("%lld",i);
n=n/i;
}else{
break;
}
}
}
例题:
P1075 质因数分解
P2043 质因子分解
void dfs(){
if(到达终点){
...
return;
}
if(越界){
return;
}
if(特殊状态){
//剪枝
return;
}
for(扩展方式){
if(扩展方式所达到状态合法){
修改操作;//根据题意来添加
标记;
dfs();
(还原);
//如果加上(还原)就是回溯法
}
}
}
void bfs(int a,int b)
{
queue < pair < int , int > > q;
q.push({
a,b});
map[a][b]= ;//根据题意填写
while(q.size())
{
auto node=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int c=dx[i]+node.first;
int d=dy[i]+node.second;
if(c>n+1 || c<0 || d>n+1 || d<0 || map[c][d]!=0){
continue;}
q.push({
c,d});
map[c][d]= ;//根据题意填写
}
}
}
例题:
P1141 01迷宫
P1332 血色先锋队
二维
for(int i=1;i<=n;i++)//枚举物品
for(int j=1;j<=v;j--)//枚举体积
//这个位置是可以正序枚举的
//一维01背包必须倒叙
if(j>=c[i]{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);//状态转移方程
}else{
dp[i][j]=dp[i-1][j];
}
一维
for(int i=1;i<=n;i++)//枚举 物品
for(int j=V;j>=c[i];j--)//枚举体积
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);//状态转移方程
例题:
P1048 采药
P1049 装箱问题
二维
for(int i=1;i<=n;i++)//枚举物品
for(int k=1;k<=v/c[i];k++)//我们的物品最多只能放件
for(int j=1;j<=t;j++){
if(k*c[i]<=j)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*c[i]]+k*w[i]);
else
dp[i][j]=f[i-1][j];
//判断条件与01背包相同
}
一维
for(int i=1;i<=n;i++)//枚举物品
for(int j=c[i];j<=v;j++)//枚举体积
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);//状态转移
例题:
P1616 疯狂的采药
P1853 投资的最大效益
普通方法(非二进制拆分法)
for(int i=1;i<=n;i++)//枚举物品
for(int j=v;j>=0;j--)//枚举体积
for(int k=1;k<=num[i],k++)
if(j-k*c[i]>=0)//判断能否装下.
dp[j]=max(dp[j],dp[j-k*c[i]]+k*w[i]);
也可以对每种物品的个物品跑01背包问题,但是效率特别低
for(int i=1;i<=n;i++)
for(int k=1;k<=num[i];k++)
for(int j=v;j>=c[i];j--)
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
不加二进制拆分例题:
P1077 摆花
P1833 樱花
二进制拆分代码
for(int i=1;i<=n;i++){
for(int j=1;j<=num[i];j<<=1)
//二进制每一位枚举.
//注意要从小到大拆分
{
num[i]-=j;//减去拆分出来的
new_c[++tot]=j*c[i];//合成一个大的物品的体积
new_w[tot]=j*w[i];//合成一个大的物品的价值
}
if(num[i])//判断是否会有余下的部分.
//就好像我们某一件物品为13,显然拆成二进制为1,2,4.
//我们余出来的部分为6,所以需要再来一份.
{
new_c[++tot]=num[i]*c[i];
new_w[tot]=num[i]*w[i];
num[i]=0;
}
}
加二进制拆分例题:
P1776 宝物筛选
P1782 旅行商的背包
for (int k=1;k<=n;k++){
for (int j=m;j>=0;j--){
for (int i= 1;i<=num[k];i++)
dp[j]=max(dp[j],dp[v-w[i]]+c[i]);
}
}
例题 :
P2851 The Fewest Coins
for(int i=1;i<=n;i++){
if(c[i]>max){
max=c[i];
}
}
for(int i=1;i<=max;i++){
for(int j=m;j>=1;j--){
for(int k=1;k<=n;k++){
if(c[k]!=i){
continue;
}
if(j<a[k]){
continue;
}
if(dp[j]<=dp[j-a[k]]+b[k]){
dp[j]=dp[j-a[k]]+b[k];
}
}
}
}
例题 :
P5322 排兵布阵
P1757 通天之分组背包
for(int i=1;i<=n;i++)//枚举主件.
{
memset(g,0,sizeof g);//做01背包要初始化.
for(now=belong[i])//枚举第i件物品的附件.
{
for(int j=v-1;j>=c[now];j--)//因为要先选择主件才能选择附件,所以我们从V-1开始.
{
g[j]=max(g[j],g[j-1]+w[now]);
}
}
g[v]=g[V-1]+w[i];
for(int j=v;j>=0;j--)
for(int k=1;k<=v;k++)//此时相当于"打包" ..
{
if(j-k>=0)
dp[j]=max(dp[j],dp[j-k]+w[i]+g[k-1]);
}
}
printf("%d",dp[v]);
例题:
P1273 有线电视网
P1064 金明的预算方案
for(int i=1;i<=n;i++){
for(int j=v;j>=a;j--)
for(int k=m;k>=b;k--)
dp[j][k]=max(dp[j][k],dp[j-a][k-b]+c);
}
例题 :
P1855 榨取kkksc03
P1507 NASA的食物计划
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i]==b[j]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
}
例题 :
P1020 导弹拦截
P1091 合唱队形
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
例题 :
P2543 奇怪的字符串
P1439 最长公共子序列
// 打算一周一更新,偶尔也会不定期的更新!
不要吝啬你的赞 QAQ