算法模板

文章目录

  • 常用头文件
  • DP部分
      • 01背包
      • 完全背包
      • 多重背包
      • LIS
      • LCS

常用头文件

/**
 *        ┏┓   ┏┓+ +
 *       ┏┛┻━━━┛┻┓ + +
 *       ┃       ┃
 *       ┃   ━   ┃ ++ + + +
 *       ████━████ ┃+
 *       ┃       ┃ +
 *       ┃   ┻   ┃
 *       ┃       ┃ + +
 *       ┗━┓   ┏━┛
 *         ┃   ┃
 *         ┃   ┃ + + + +
 *         ┃   ┃    Code is far away from bug with the animal protecting
 *         ┃   ┃ +     神兽保佑,代码无bug
 *         ┃   ┃
 *         ┃   ┃  +
 *         ┃    ┗━━━┓ + +
 *         ┃        ┣┓
 *         ┃        ┏┛
 *         ┗┓┓┏━┳┓┏┛ + + + +
 *          ┃┫┫ ┃┫┫
 *          ┗┻┛ ┗┻┛+ + + +
 */
/*--------- Hongjie ----------*/
// #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long ll;
typedef pair<int ,int> P;

const int INF  = 0x3f3f3f3f;
const int MAXN = 1e5+7;


int main(){
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);



        return 0;
}

DP部分

01背包

int dp[MAXN];
for(int i=0;i<n;i++)
    for(int j=W;j>=w[i];j--)
        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%d\n",dp[W]);

完全背包

int dp[MAXN];
for(int i=0;i<n;i++)
    for(int j=w[i];j<=W;j++)
        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%d\n",dp[W]);

多重背包

(第i种背包最多可以选择m[i]种)

for(int i=0;i<n;i++){
    int num=m[i];//用来找a 
    for(int k=1;num>0;k<<=1){
        int mul=min(k,num);
        for(int j=W;j>=w[i]*mul;j--){
            dp[j]=max(dp[j],dp[j-w[i]*mul]+v[i]*mul); 
        }
        num-=mul;
    }
}
printf("%d\n",dp[W]);

LIS

最长递增子序列(长度+打印路径)

#include
using namespace std;
const int MAXN=105;
int a[MAXN];
int dp[MAXN];
int n;
int vis[MAXN];
void dfs(int pos)//打印路径 
{
	if(pos==-1)	return  ;
	dfs(vis[pos]);
	printf(" %d",pos+1);//这里是正序输出编号(从1开始的) 
}
int main()
{
	while(~scanf("%d",&n)&&n)
	{
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		memset(dp,0,sizeof(dp));
		memset(vis,-1,sizeof(vis));
		int res=0;
		int pos=-1;		
		for(int i=0;i<n;i++)
		{
			dp[i]=1;
			for(int j=0;j<i;j++)
				if(a[i]>a[j])
				{
					if(dp[i]<dp[j]+1)
					{
						dp[i]=dp[j]+1;
						vis[i]=j;//vis[i]=j 表示以a[i]为结尾的LIS的上一个元素是a[j]		
					}
				}	
			if(res<dp[i])
			{
				res=dp[i];
				pos=i;//找到LIS的最后一个结点 
			}
		}
		printf("The number is %d:",res);//输出LIS的长度 
		dfs(pos);
		printf("\n");
	}
	return 0;
}

LCS

最长公共子序列(长度+打印路径)

#include
#include
#include
using namespace std;
const int  maxn=1009;
char a[maxn],b[maxn];
int path[maxn][maxn],dp[maxn][maxn];//path 记录路径 
 
void lcs(int i,int j)//打印路径 
{
	if(i==0||j==0)	return ;//结束标志,a或者b只要有一个找完了,就不在找了 
	if(path[i][j]==1)//path是1的时候输出这个字符 
	{
		lcs(i-1,j-1);//因为是从后往前找的 
		printf("%c",a[i-1]);//所以这句得写到递归函数下边 
	 } 
	else if(path[i][j]==2)
		lcs(i-1,j);
	else 
		lcs(i,j-1);
	return ;
}
 
int main()
{
	while(~scanf("%s %s",a,b))
	{
		memset(dp,0,sizeof(dp));
		int m=strlen(a);
		int n=strlen(b);
		for(int i=1;i<=m;i++)
			for(int j=1;j<=n;j++)
				if(a[i-1]==b[j-1])
				{
					dp[i][j]=dp[i-1][j-1]+1;
					path[i][j]=1;
				}
				else if(dp[i-1][j]>dp[i][j-1])
				{
					dp[i][j]=dp[i-1][j];
					path[i][j]=2;
				}
				else
				{
					dp[i][j]=dp[i][j-1];	
					path[i][j]=3;
				}
		
		lcs(m,n);		
		printf("\n"); 
//		printf("\n%d\n",dp[m][n]);//输出最长子序列的长度 
	}
	return 0;

你可能感兴趣的:(算法模板,其他)