1. 程式人生 > >金明的預算方案-DP

金明的預算方案-DP

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;
}