vijosP1059 积木城堡

vijosP1059 积木城堡

链接:https://vijos.org/p/1059

【思路】

   01背包。

   刚开始想麻烦了,想的是二分答案然后01背包判断是否可行,但是首先答案不满足单调性所以不能二分(这点以后做题之前一定要想清楚),其次如果从大到小枚举依次判定的话会TLE。

   不得不说自己真是笨。

   其实可以对每一组积木用一次01背包,用一个cnt记录满足该高度的城堡数目。然后从大到小检查如果为n输出即可。时间上是O(n^3)。

【代码】

 1 #include<iostream>
 2 #include<cstring>
 3 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 4 using namespace std;
 5 
 6 const int maxn = 100+10;
 7 
 8 int h[maxn][maxn],sum[maxn];
 9 bool d[maxn*maxn];
10 int cnt[maxn*maxn];
11 int n;
12 
13 void dp(int tot,int* A) {
14     int len=A[0];
15     d[0]=true;
16     FOR(i,1,len)
17        for(int j=tot;j>=A[i];j--)
18        {
19           d[j] = d[j] || d[j-A[i]];
20        }
21     FOR(i,0,tot+1) cnt[i] += d[i];
22 }
23 
24 int main() {
25     ios::sync_with_stdio(false);
26     cin>>n;
27     int x,R=0;
28     FOR(i,0,n) {
29         h[i][0]=1;
30         while(cin>>x && x!=-1) {
31             h[i][h[i][0]++]=x;
32             sum[i] += x;
33         }
34         R=max(R,sum[i]);
35     }
36 
37     FOR(j,0,n) 
38     {
39        memset(d,0,sizeof(d));
40        dp(sum[j],h[j]);
41     }
42     for(int i=R;i>=0;i--)
43        if(cnt[i]>=n) {
44               cout<<i<<"
";
45               break;
46        }
47     return 0;
48 }
原文地址:https://www.cnblogs.com/lidaxin/p/4904612.html