TYVJ1299
这题纠结了N久,就是想不通,8000个人每个人用一次8000*8000的01背包,后来看别人的题解也看不下去,然后不知道看到了点什么,突然灵光一闪,打表!
其实也不算是打表了。。一开始想不到这个主要还是因为二维的01背包用的太少了,以前都是偷懒用一维,(这里用二维的也不行,会MLE,只要把每次i循环完后的dp[Total_v])保存一下就好了,然后根据每个孩子手上的数字是多少,就能得出他的身高。
身高问题说完了,就是简单的01背包
然后求什么“环形最长上升子序列”,丫的它这么说就是坑你呢,让你往dp那方向想,仔细看题就知道,可以在这个圈里转很多很多次,每次可以只选出一个人,也就是把孩子们的身高从小到大排序,然后找出把重复的去掉,不重复的统计一下,输出就好
总的来说这题还是不错的,最起码让人更深的理解了01背包
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 8001; 7 const int maxv = 8001; 8 int dp[maxv],a[maxn],w[maxn],v[maxn],h[maxn],s[maxn]; 9 int main() 10 { 11 //freopen("in.txt","r",stdin); 12 int n,m,c; 13 cin>>n>>m>>c; 14 for(int i = 1;i<=n;++i)scanf("%d",a+i); 15 for(int i = 1;i<=m;++i)scanf("%d",v+i); 16 for(int i = 1;i<=m;++i)scanf("%d",w+i); 17 memset(dp,0,sizeof(dp)); 18 for(int i = 1;i<=m;++i) 19 { 20 for(int j = c;j>=w[i];--j) 21 dp[j] = max(dp[j],dp[j-w[i]]+v[i]); 22 s[i] = dp[c]; 23 } 24 for(int i = 1;i<=n;++i) 25 h[i] = s[a[i]]; 26 sort(h+1,h+1+n); 27 int ans[maxn],cnt = 0; 28 ans[cnt++] = h[1]; 29 for(int i = 2;i<=n;++i) 30 { 31 if(h[i]==h[i-1])continue; 32 else ans[cnt++] = h[i]; 33 } 34 cout<<cnt<<endl; 35 for(int i = 0;i<cnt;++i) 36 cout<<ans[i]<<" "; 37 cout<<endl; 38 39 40 return 0; 41 }
弱者究竟为何而战?!