【題解】「P1504」積木城堡
阿新 • • 發佈:2020-07-22
這題是01揹包(\(DP\))
如何判斷要拆走那個積木,首先定義一個\(ans\)陣列,來存放這對積木能拼成多高的,然後如果\(ans_i = n\)那麼就說明這個高度的積木可以。
話不多說,上程式碼!
#include<cstdio> //從最小高度~1列舉, 如果能恰好達到這個高度(即用它有的積木恰好能拼出)有n個城堡 #include<cstring> #include<algorithm> using namespace std; int n, len, min_high = 2e9; //n表示城堡數,len表示每塊立方體積木的稜長, min_high表示所有城堡初始高度最小值 int w[10005],ans[10005]; //設ans[i]表示i能被多少組w[1..n]湊成,當dp[i]==true時,ans[i]++ //w[i]表示組成這座城堡的第i塊積木的稜長 bool dp[10005]; //dp[i]表示能否使用當前的w[1..n]相加得到i /* 有n件物品(積木),每件物品體積(積木的稜長)為w[i], 價值(積木的稜長)為w[i]。 有容量(城堡高度)為 V 的揹包(城堡)。求在容量(城堡高度)允許的範圍下,揹包裝入物品的價值和(積木的稜長和)有哪些可能值。*/ int main() { scanf("%d", &n); for(int k = 1; k <= n; k++) { memset(dp, 0, sizeof(dp)); int cnt = 1, high = 0; //cnt表示每座城堡含積木的塊數,high表示每座城堡的初始高度 while(1) { scanf("%d", &w[cnt]); //len表示組成這座城堡的每塊積木的稜長 if(w[cnt] == -1) break; high += w[cnt]; cnt++; } dp[0] = 1; // dp[0] = 1表示能使用當前的w[1..n]相加得到高度0 min_high = min(min_high, high); //求出所有城堡初始高度最小值 for(int i = 1; i < cnt; i++) //對每座城堡從1~g去列舉每一塊積木 for(int j = high; j >= w[i]; j--) dp[j] = dp[j] || dp[j-w[i]]; //01揹包變形,即動態轉移方程 for(int i = high; i >= 1; i--) if(dp[i] == true) ans[i]++; //統計高度i出現次數 } for(int i = min_high; i >= 1; i--) //從最小高度~1列舉 if(ans[i] == n) //如果能恰好達到這個高度(即用它有的積木恰好能拼出)有n個城堡 { printf("%d\n", i); return 0; } printf("0\n"); return 0; }
\(Bye Bye!\)