1.P1064 [NOIP2006 提高组] 金明的预算方案
01背包dp模板
#include <iostream>
using namespace std;
int dp[160];
struct node
{
int val;
int vol;
}a[160];
int main()
{
int w,n;
cin>>n>>w;
for(int i=1;i<=n;i++)
{
cin>>a[i].val;
cin>>a[i].vol;
}
for(int i=1;i<=n;i++)
{
for(int j=w;j>a[i].vol;j--)
{
dp[j]=max(dp[j],dp[j-a[i].vol]+a[i].val);
}
}
cout<<dp[w]<<endl;
return 0;
}
不选附件的①:f[j] = max(f[j],f[j-main_item_w[i]]+main_item_c[i]);
选附件1的②:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] ] + main_item_c[i] + annex_item_c[i][1]);
选附件2的③:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][2]);
选附件1和附件2的④:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][1] + annex_item_c[i][2]);
#include <iostream>
#define maxn 32005
using namespace std;
int n,m;
int v,p,q;
int main_item_w[maxn];
int main_item_c[maxn];
int annex_item_w[maxn][3];
int annex_item_c[maxn][3];
int f[maxn];
int main(){
cin >> n >> m;
for (int i=1;i<=m;i++){
cin >> v >> p >> q;
if (!q){
main_item_w[i] = v;
main_item_c[i] = v * p;
}
else{
annex_item_w[q][0]++;
annex_item_w[q][annex_item_w[q][0]] = v;
annex_item_c[q][annex_item_w[q][0]] = v * p;
}
}
for (int i=1;i<=m;i++)
for (int j=n;main_item_w[i]!=0 && j>=main_item_w[i];j--){
f[j] = max(f[j],f[j-main_item_w[i]]+main_item_c[i]);
if (j >= main_item_w[i] + annex_item_w[i][1])
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] ] + main_item_c[i] + annex_item_c[i][1]);
if (j >= main_item_w[i] + annex_item_w[i][2])
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][2]);
if (j >= main_item_w[i] + annex_item_w[i][1] + annex_item_w[i][2])
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][1] + annex_item_c[i][2]);
}
cout << f[n] << endl;
return 0;
}
2.P1006 [NOIP2008 提高组] 传纸条
其实就是矩阵求最大和问题
模板:
#include<iostream>
using namespace std;
int n,m;
int a[51][51],dp[51][51];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
dp[i][j]+=a[i][j];
}
printf("%d\n",dp[n][m]);
return 0;
}
ac代码:
#include<iostream>
using namespace std;
int n,m;
int a[51][51],dp[51][51][51][51];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=n;k>=1;k--)
for(int l=m;l>=1;l--)
{
dp[i][j][k][l]=max(dp[i-1][j][k-1][l],max(dp[i-1][j][k][l-1],max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1])));
dp[i][j][k][l]+=((i==k&&j==l)?a[i][j]:(a[i][j]+a[k][l]));
}
printf("%d\n",dp[n][m][n][m]);
return 0;
}
但是为什么求矩阵最小和不好使