TYVJ1190
新技能get!
首先先说一个小模型吧算是,给你n个数,求这n个数能组成的数有哪些(前提n和a[i]不能太大),这n个数的和为sum
开一个标记数组vis[i][j]表示前i个数是否可以组成j初始化vis[i][j]为0,vis[i][0]=1(0<=i<=n)(意思就是一个数也不选,组成的数为0)
然后枚举a[i],对于每个a[i],枚举j = sum->a[i];
for(int i = 1;i<=n;++i)
for(int j = sum;j>=a[i];--j)
if(vis[i-1][j-a[i]])
vis[i][j] = vis[i][j-a[i]] = 1;
大致分析一下这段代码,一开始标记了vis[i][0] = 1;
如果在i-1层时j-a[i] 已经出现了,那么它再加上a[i]就得j,即j可以被表示,则在第i层把j和j-a[i]两个数标记
最后扫一遍vis[n][i]就知道可以组合出哪些数了
这里因为只用到上一层的vis[][]并且不改变其值,则空间也可以优化到1维,只需要vis[j]表示j是否可以组合出j(如果是一维的话,j只能倒着枚举)
说到这里这道题的主要核心基本上说完了,好像什么都还没说?
这道题要求的是最大的相同的高度,只要求出每个城堡所能变为的高度,用cnt[]数组记录下每个高度出现的次数,则选出cnt[i]==n的i的最大值即是。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 105; 7 int a[maxn],vis[10005],cnt[10005]; 8 int main() 9 { 10 //freopen("in.txt","r",stdin); 11 int n; 12 memset(cnt,0,sizeof(cnt)); 13 while(cin>>n) 14 { 15 for(int k = 1;k<=n;++k) 16 { 17 memset(vis,0,sizeof(vis)); 18 int m = 1,t,sum = 0; 19 while(~scanf("%d",&t)&&t!=-1) 20 { 21 a[m++] = t; 22 sum+=t; 23 } 24 vis[0] = 1; 25 for(int i = 1;i<m;++i) 26 for(int j = sum;j>=a[i];--j) 27 if(vis[j-a[i]])vis[j] = 1; 28 for(int i = 0;i<=sum;++i) 29 if(vis[i])cnt[i]++; 30 } 31 for(int i = 10000;i>=0;i--) 32 if(cnt[i]==n) 33 { 34 printf("%d\n",i); 35 break; 36 } 37 38 } 39 return 0; 40 }
弱者究竟为何而战?!