题意:有n个品牌,每个品牌至少买一件。
01背包加上一维,设计状态dp[k][i]表示前k种花费i所取得的最大值,状态可由前k-1种和当前品牌取得,注意初始化和方程的位置(无后效性)。
View Code
1 /* 2 Author:Zhaofa Fang 3 Lang:C++ 4 */ 5 #include <cstdio> 6 #include <cstdlib> 7 #include <sstream> 8 #include <iostream> 9 #include <cmath> 10 #include <cstring> 11 #include <algorithm> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 #include <queue> 16 #include <stack> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define REP(i,n) for(int i=0;i < (n);i++) 24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 26 #define PII pair<int,int> 27 #define PB push_back 28 #define MP make_pair 29 #define ft first 30 #define sd second 31 #define lowbit(x) (x&(-x)) 32 #define INF (1<<30) 33 34 int dp[11][10005]; 35 vector<int>p[11],v[11]; 36 int main() 37 { 38 //freopen("in","r",stdin); 39 //freopen("out","w",stdout); 40 int n,m,K; 41 while(~scanf("%d%d%d",&n,&m,&K)) 42 { 43 int a,b,c; 44 REP(i,11)p[i].clear(),v[i].clear(); 45 REP(i,n) 46 { 47 scanf("%d%d%d",&a,&b,&c); 48 p[a].PB(b); v[a].PB(c); 49 } 50 memset(dp,-1,sizeof(dp)); 51 REP(i,m+1)dp[0][i] = 0; 52 FOR(k,1,K) 53 { 54 REP(j,v[k].size()) 55 { 56 FORD(i,m,p[k][j]) 57 { 58 if(dp[k][i-p[k][j]]!=-1)//若两方程交换位置,则不满足dp的无后效性原则,可由第二组数据得知 59 dp[k][i] = max(dp[k][i],dp[k][i-p[k][j]]+v[k][j]); 60 61 if(dp[k-1][i-p[k][j]]!=-1) 62 dp[k][i] = max(dp[k][i],dp[k-1][i-p[k][j]]+v[k][j]); 63 64 //DEBUG(k),DEBUG(i),DEBUG(dp[k][i]); 65 } 66 } 67 } 68 int ans = -1; 69 FOR(j,0,m)ans = max(ans,dp[K][j]); 70 if(ans!=-1)printf("%d\n",ans); 71 else puts("Impossible"); 72 } 73 return 0; 74 } 75 /* 76 3 5 3 77 1 2 5 78 2 2 1 79 3 2 2 80 81 3 5 3 82 1 0 5 83 2 0 1 84 3 0 2 85 86 5 10000 3 87 1 4 6 88 2 5 7 89 3 4 99 90 1 55 77 91 2 44 66 92 ans: 93 Impossible 94 8 95 255 96 */