C++模板总结(持续更新)

说明 : 此模板是供loony复习用的,如有瑕疵误喷!!!
友情提示 : 次文章仅展示模板,没有讲解部分哦!

以下是正文:

数学

1. gcd (辗转相除法)

int gcd(int a, int b) {
     
    if (b == 0) {
     
        return a;
    }
    return gcd(b, a % b);
}

例题:

P2118 比例简化
P1372 又是毕业季I

2. lcm

int lcm(int a, int b) {
     
    return a * b / gcd(a, b);
}

例题:

P1029 最大公约数和最小公倍数问题

3. 线性筛

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 线性筛素数

4. 判断素数

int is_prime(int n){
     
	for(int i=2;i*i<=n;i++){
     
		if(n%i==0){
     
			return 0;
		}
	}
	return 1;
}

例题:

AT1476 素数判定
P1217 回文质数

5. 分解质因数

for(int i=2;i<=n;i++){
     
	while(n!=1){
     
		if(n%i==0){
     
			printf("%lld",i);
			n=n/i;
		}else{
     
			break;
		}
	}
}

例题:

P1075 质因数分解
P2043 质因子分解

搜索

1. dfs


void dfs(){
       
    if(到达终点){
       
        ...
        return;  
    }  
    if(越界){
     
        return; 
    }
    if(特殊状态){
     //剪枝
        return;
    }
    for(扩展方式){
       
        if(扩展方式所达到状态合法){
       
            修改操作;//根据题意来添加  
            标记;  
            dfs();  
            (还原)//如果加上(还原)就是回溯法  
        }  
 
    }  
} 

2. bfs

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 血色先锋队

动态规划

1. 01背包

二维

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 装箱问题

2. 完全背包

二维

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 投资的最大效益

3. 多重背包

普通方法(非二进制拆分法)

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 旅行商的背包

4. 混合背包

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

5. 分组背包

	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 通天之分组背包

6. 有依赖的背包

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 金明的预算方案

7. 二维费用背包

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的食物计划

8. 最长上升子序列

 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 合唱队形

9. 最长公共子序列

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

你可能感兴趣的:(C++模板总结(持续更新))