Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1334 Accepted Submission(s): 666
Here is the link:http://acm.hdu.edu.cn/showproblem.php?pid=2602
Today we are not desiring the maximum value of bones,but the K-th maximum value of the bones.NOTICE that,we considerate two ways that get the same value of bones are the same.That means,it will be a strictly decreasing sequence from the 1st maximum , 2nd maximum .. to the K-th maximum.
If the total number of different values is less than K,just ouput 0.
// dp[s][i][k] 表示在用了 s 空间 i 件物品后排在第k位的值是多少
dp[s][i][1..k] 在 dp[s][i][1..k] 和 dp[s-s[i]][i-1][1..k] 这2k 个数据中找到前 k 名就是了
就像学校想知道一个年级的前十名 ,只要知道每个班的前十 而过程则是只要比较每2个班的前十、就可以知道全校前十
#include <iostream> #include <algorithm> #include <queue> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; int dp[1010][40]; int s[110],p[110]; int main() { int N,V,K; int T; scanf("%d",&T); while(T--){ int i,j,k; scanf("%d %d %d",&N,&V,&K); int t1[40],t2[40]; for(i=1;i<=N;i++) scanf("%d",&p[i]); for(i=1;i<=N;i++) scanf("%d",&s[i]); memset(dp,0,sizeof(dp)); for(i=1;i<=N;i++){ for(j=V;j>=s[i];j--){ for(k=1;k<=K;k++) { t1[k]=dp[j-s[i]][k]+p[i]; t2[k]=dp[j][k]; } t1[k]=t2[k]=-1; int a=1,b=1; for(k=1;(a<=K||b<=K)&&k<=K;){ if(t1[a]>t2[b]) dp[j][k]=t1[a++]; else dp[j][k]=t2[b++]; if(dp[j][k]!=dp[j][k-1]) k++; } } } printf("%d\n",dp[V][K]); } return 0; }