题解集
背包问题的正逆序讲解
01背包:dp[i][j] =max(dp[i-1][j-value[i]]+w[i] , dp[i-1][j])
完全背包:dp[i][j] =max(dp[i][j-value[i]]+w[i] , dp[i-1][j])
一维表现形式:f[i] = max(f[i], f[i-weight[j]] + value[j])
完全背包应选择根据当前的状态值来更新本次的结果,所以正向循环
01背包应选择根据上一次的状态值来更新本次的结果,所以逆向循环
//01背包
#include <iostream>
using namespace std;
#define maxn 10000007
long long t,m,tim[maxn],value[maxn],dp[maxn],ans[maxn];
int main()
{
long long i,j;
cin>>t>>m;
for(i=0;i<m;i++)
cin>>tim[i]>>value[i];
for(i=0;i<m;i++)
{
for(j=t;j>=0;j--)//逆序
{
if(j>=tim[i])
{
dp[j]=max(dp[j],dp[j-tim[i]]+value[i]);
}
}
}
cout <<dp[t]<<endl;
return 0;
}
//完全背包
#include <iostream>
using namespace std;
#define maxn 10000007
long long t,m,tim[maxn],value[maxn],dp[maxn],ans[maxn];
int main()
{
long long i,j;
cin>>t>>m;
for(i=0;i<m;i++)
cin>>tim[i]>>value[i];
for(i=0;i<m;i++)
{
for(j=tim[i];j<=t;j++)//正序
{
if(j>=tim[i])
{
dp[j]=max(dp[j],dp[j-tim[i]]+value[i]);
}
}
}
cout <<dp[t]<<endl;
return 0;
}
//01背包
#include <iostream>
using namespace std;
int lose[1005],win[1005],use[1005];
long long dp[1005];
int main()
{
int n,m;
int i,j;
cin>>n>>m;
for(i=0;i<n;i++)
cin>>lose[i]>>win[i]>>use[i];
for(i=0;i<n;i++)
{
for(j=m;j>=0;j--)
{
if(j>=use[i])
dp[j]=max(dp[j-use[i]]+win[i],dp[j]+lose[i]);
else
dp[j]+=lose[i];
}
}
cout <<5*dp[m]<< endl;
return 0;
}
P2758编辑距离
设dp(i,j)表示将长度为i的字符串转为长度为j的字符串
1、删除一个字符:dp(i,j)=dp(i-1,j)+1
2、插入一个字符:dp(i,j)=dp(i,j-1)+1
3、将一个字符改为另一个字符:dp(i,j)=dp(i-1,j-1)+1
#include <iostream>
#include<cstring>
using namespace std;
char a[2006],b[2006];
int dp[2006][2006],lena,lenb;
int dplen(char a[],char b[])
{
int i,j;
//初始化
for(i=1;i<=lena;i++)
dp[i][0]=i;
for(j=1;j<=lenb;j++)
dp[0][j]=j;
for(i=1;i<=lena;i++)
for(j=1;j<=lenb;j++)
{
if(a[i-1]==b[j-1])
dp[i][j]=dp[i-1][j-1];
else
dp[i][j]=1+min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]);
}
return dp[lena][lenb];
}
int main()
{
cin>>a>>b;
lena=strlen(a);
lenb=strlen(b);
int ans=dplen(a,b);
cout <<ans<< endl;
return 0;
}