vijosP1059 积木城堡
【思路】
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<<"\n"; 45 break; 46 } 47 return 0; 48 }