金明的預算方案-DP
阿新 • • 發佈:2018-12-24
https://vjudge.net/problem/HRBUST-1377
本題由三種思路,但是第三種和第一種感覺差不多。
1 可以發現一個物品最多五種狀態。於是用5種狀態進行01揹包。
要注意 狀態轉移的過程。
2 樹形dp,其實也是01揹包的層次過程。。
3 分組揹包,寫了一個沒對。。也是製造4個揹包,每四個分成一組,每組只能取一個。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=70;
int a[maxn];
int b[maxn];
int belong[maxn];
int dp[maxn][32100];
int m,n;
int treedp(int cost,int num){
if(cost>0){
for(int i=1;i<=n;i++){
if(belong[i]==num)//如果屬於是當前節點的自孩子揹包
{ for(int j=0;j<=cost-a[i];j++)
dp[i][j]=dp[num][j]+a[i]*b[i];//裝進去這個點。
treedp(cost-a[i],i);
for (int x=0;x<=cost;x++)
if(x>=a[i])
dp[num][x]=max(dp[num][x],dp[i][x-a[i]]);
else
dp[num][x]=dp[num][x];
}
}
}
return 0;
}
int main()
{
while(~scanf("%d%d",&m,&n)){
//m/=100;
memset(dp,0 ,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i],&b[i],&belong[i]);
}
treedp(m,0);
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++)
printf("%d ",dp[i][j]);
cout<<endl;
}
printf("%d\n",dp[0][m]);
}
return 0;
}
轉化成01揹包
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
/*第一種方法:直接分5種情況。
每種進行01 揹包(意思就是啊,
這5種情況只會發生一種情況)
第二種:
*/
const int maxn = 40000;
int dp[70][maxn];
int value[70][3],imp[70][3];
int main()
{
int n,m;
int v,p,q;
while(~scanf("%d%d",&m,&n)){
memset(value,0,sizeof(value));
memset(imp,0,sizeof(imp));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%d%d%d",&v,&p,&q);
if(!q){
value[i][0]=v;
imp[i][0]=p;
}
else{
if(!value[q][1]){
value[q][1]=v;
imp[q][1]=p;
}
else{
value[q][2]=v;
imp[q][2]=p;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j>=value[i][0]){
dp[i][j]=max(dp[i-1][j],dp[i-1][j-value[i][0]]+value[i][0]*imp[i][0]);
if(j>=(value[i][0]+value[i][1]))
dp[i][j]=max(dp[i][j],dp[i-1][j-value[i][0]-value[i][1]]+value[i][0]*imp[i][0]+value[i][1]*imp[i][1]);
if(j>=(value[i][0]+value[i][2]))
dp[i][j]=max(dp[i][j],dp[i-1][j-value[i][0]-value[i][2]]+value[i][0]*imp[i][0]+value[i][2]*imp[i][2]);
if(j>=(value[i][0]+value[i][2]+value[i][1]))
dp[i][j]=max(dp[i][j],dp[i-1][j-value[i][0]-value[i][2]-value[i][1]]+value[i][0]*imp[i][0]+value[i][2]*imp[i][2]+value[i][1]*imp[i][1]);
}
else
dp[i][j]=dp[i-1][j];
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}