1. 程式人生 > >[NOIP2006]金明的預算方案

[NOIP2006]金明的預算方案

嘟嘟嘟

 

這雖然是一道水題,然而我Debug了快一個點兒,於是決定在A了之後發篇部落格。

 

這顯然是一個有依賴性的揹包問題,但是因為這道題一個主件最多隻有兩個附件,所以只有4種情況:

1.只選主件

2.主件+附件1

3.主件+附件2

4.主件+附件1+附件2

(5.都不選)

而且這四種情況是互斥的,那麼這就相當於分組揹包中的一個組,把原始的物品拆成上述新的物品(組合)後,跑正常的分組揹包就行。

題解裡面開了個vector記錄了每一個組(程式碼巨醜)。

 1 #include<cstdio>
 2 #include<iostream>
 3
#include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cctype> 7 #include<cstdlib> 8 #include<queue> 9 #include<stack> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15
#define rg register 16 #define pr pair<int, int> 17 #define mp make_pair 18 typedef long long ll; 19 typedef double db; 20 const db eps = 1e-8; 21 const int INF = 0x3f3f3f3f; 22 const int maxm = 65; 23 const int maxn = 32005; 24 inline ll read() 25 { 26 ll ans = 0; 27 char ch = getchar(), las = '
'; 28 while(!isdigit(ch)) las = ch, ch = getchar(); 29 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 30 if(las == '-') ans = -ans; 31 return ans; 32 } 33 inline void write(ll x) 34 { 35 if(x < 0) putchar('-'), x = -x; 36 if(x >= 10) write(x / 10); 37 putchar(x % 10 + '0'); 38 } 39 40 int m,n; 41 vector<int> item[maxm]; 42 struct Node 43 { 44 int v, p, q; 45 }e[maxm]; 46 47 vector<pr> v[maxm]; 48 int cnt = 0; 49 ll dp[maxm][maxn]; 50 51 int main() 52 { 53 n = read(); m = read(); 54 for(int i = 1; i <= m; ++i) 55 { 56 e[i].v = read(); e[i].p = read(); e[i].q = read(); 57 if(e[i].q) item[e[i].q].push_back(i); 58 } 59 for(int i = 1; i <= m; ++i) 60 { 61 if(item[i].size()) 62 { 63 v[++cnt].push_back(mp(e[i].v, e[i].v * e[i].p)); 64 v[cnt].push_back(mp(e[i].v + e[item[i][0]].v, e[i].v * e[i].p + e[item[i][0]].v * e[item[i][0]].p)); 65 if(item[i].size() == 2) 66 { 67 v[cnt].push_back(mp(e[i].v + e[item[i][1]].v, e[i].v * e[i].p + e[item[i][1]].v * e[item[i][1]].p)); 68 v[cnt].push_back(mp(e[i].v + e[item[i][0]].v + e[item[i][1]].v, e[i].v * e[i].p + e[item[i][0]].v * e[item[i][0]].p + e[item[i][1]].v * e[item[i][1]].p)); 69 } 70 } 71 else if(!e[i].q) v[++cnt].push_back(mp(e[i].v, e[i].v * e[i].p)); 72 } 73 for(int k = 1; k <= cnt; ++k) 74 for(int i = 0; i < (int)v[k].size(); ++i) 75 for(int j = n; j >= 0; --j) 76 { 77 dp[k][j] = max(dp[k][j], dp[k - 1][j]); 78 if(j - v[k][i].first >= 0) dp[k][j] = max(dp[k][j], dp[k - 1][j - v[k][i].first] + v[k][i].second); 79 write(dp[cnt][n]), enter; 80 return 0; 81 }
View Code

 

 

題解到此結束,下面是我debug過程:

1.快速的寫完且過了樣例後,交上去只有20,然後發現寫成了01揹包。

2.開始改成分組揹包,因為組數的序號問題出現了空的組,debug了10多分鐘。

3.最後改完後還是gg,下載的樣例過不去,陷入無窮的debug過程。

4.終於發現竟然是分組揹包寫錯了,原來01揹包偷懶的寫法for(int j = m; i >= c[i]; --j)在分組揹包裡是錯的,這樣會導致一些好的狀態沒有繼承,所以還是乖乖從m列舉到0吧……