积木城堡-DP
题目:
Problem C. 积木城堡
时间限制 1000 ms
内存限制 128 MB
题目描述
XC的儿子小XC最喜欢玩的游戏用积木垒漂亮的城堡。城堡是用一些立方体的积木垒成的,城堡的每一层是一块积木。小XC是一个比他爸爸XC还聪明的孩子,他发现垒城堡的时候,如果下面的积木比上面的积木大,那么城堡便不容易倒。所以他在垒城堡的时候总是遵循这样的规则。
小XC想把自己垒的城堡送给幼儿园里漂亮的女孩子们,这样可以增加他的好感度。为了公平起见,他决定把送给每个女孩子一样高的城堡,这样可以避免女孩子们为了获得更漂亮的城堡而引起争执。可是他发现自己在垒城堡的时候并没有预先考虑到这一点。所以他现在要改造城堡。由于他没有多余的积木了,他灵机一动,想出了一个巧妙的改造方案。他决定从每一个城堡中挪去一些积木,使得最终每座城堡都一样高。为了使他的城堡更雄伟,他觉得应该使最后的城堡都尽可能的高。
任务:
请你帮助小XC编一个程序,根据他垒的所有城堡的信息,决定应该移去哪些积木才能获得最佳的效果。
输入数据
第一行是一个整数N(N<=100) , 表示一共有几座城堡。以下 N 行每行是一系列非负整数,用一个空格分隔,按从下往上的顺序依次给出一座城堡中所有积木的棱长。用-1结束。一座城堡中的积木不超过100块,每块积木的棱长不超过100。
输出数据
一个整数,表示最后城堡的最大可能的高度。如果找不到合适的方案,则输出 。
样例输入
2
2 1 –1
3 2 1 –1
样例输出
3
思路:①将所有城堡能表示的高度存储起来②求交集里的最大值
值得学习的是这里用DP求子集的办法,非常之妙啊!假定dp[h-b]缺失当前块的高度可达,那么当前块加入之后,变成dp[h],h高度可达。注意一下更新状态的前后顺序
#include <bits/stdc++.h>
using namespace std;int main()
{int n;cin>>n;vector<vector<bool>>castel(n);//存储所有城堡的所有高度int min_total=1e5;//假定一个最高的高度for(int i=0;i<n;i++){int sum=0;vector<int>blocks;int h;while( cin>>h){if(h==-1){break;}blocks.push_back(h);sum+=h;}min_total=min(min_total,sum);vector<bool>dp(sum+1,false);//dp存储所有可达的高度,求子集和dp[0]=true;for(int b:blocks){for(int h=sum;h>=b;h--){if(dp[h-b]){dp[h]=true;}}}castel[i]=dp; }//求交集int ans=0;for(int i=min_total;i>=0;i--){bool ok=true;for(int j=0;j<n;j++){if(i>castel[j].size()||!castel[j][i]){ok=false;break;}}if(ok){ans=i;break;}}cout<<ans<<"\n";}
