标签:
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3437 Accepted Submission(s): 1773
/* Accepted 2639 858MS 5372K 831 B G++ */ #include"cstdio" #include"cstring" #include"algorithm" using namespace std; const int MAXN=1005; int dp[MAXN][MAXN]; int n,W,K; int v[MAXN],w[MAXN]; int vec[MAXN],cnt; bool comp(int x,int y) { return x > y; } void KthZeroOnePack() { for(int i=0;i<n;i++) { for(int j=W;j>=w[i];j--) { cnt=0; for(int th=1;th<=K;th++) { vec[cnt++]=dp[j][th]; vec[cnt++]=dp[j-w[i]][th]+v[i]; } sort(vec,vec+cnt,comp); cnt=unique(vec,vec+cnt)-vec; for(int th=1;th<=min(cnt,K);th++) dp[j][th]=vec[th-1]; } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&W,&K); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) scanf("%d",&v[i]); for(int i=0;i<n;i++) scanf("%d",&w[i]); KthZeroOnePack(); printf("%d\n",dp[W][K]); } return 0; }
上面用了STL里的sort函数速度较慢...
因为dp[j][1]...dp[j][k]与dp[j-w[i]][1]+v[i]...dp[j-w[i]][k]+v[i]是依次递减的,那么我们可以用两个数组将这两组数组保存起来,再O(N)的时间内求得第K大。
/* Accepted 2639 171MS 5372K 966 B G++ */ #include"cstdio" #include"cstring" #include"algorithm" #include"queue" using namespace std; const int MAXN=1005; int dp[MAXN][MAXN]; int n,W,K; int v[MAXN],w[MAXN]; int s1[MAXN],s2[MAXN]; void KthZeroOnePack() { for(int i=0;i<n;i++) { for(int j=W;j>=w[i];j--) { for(int th=1;th<=K;th++) { s1[th-1]=dp[j][th]; s2[th-1]=dp[j-w[i]][th]+v[i]; } s1[K]=s2[K]=-1; int cnt=1; int cnt1=0,cnt2=0; while(cnt<=K&&(s1[cnt1]!=-1||s2[cnt2]!=-1)) { if(s1[cnt1]>s2[cnt2]) dp[j][cnt]=s1[cnt1++]; else dp[j][cnt]=s2[cnt2++]; if(dp[j][cnt]!=dp[j][cnt-1]) cnt++; } } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&W,&K); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) scanf("%d",&v[i]); for(int i=0;i<n;i++) scanf("%d",&w[i]); KthZeroOnePack(); printf("%d\n",dp[W][K]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/program-ccc/p/5187676.html