这个题目是求解第k小01背包, 我们只需要再多加一维表示容量为j时的价值即可。。代码里面用了归并排序的思想来求解f[j][k], 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int f[1000+10][35]; int A[35], B[35]; //A选 B不选 int W[100+10], V[100+10]; int N, v, K; void print(int a[], int s, int e) { for(int i=s; i<=e; i++) printf("%d%c", a[i], i==e?‘\n‘:‘ ‘); } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d%d", &N, &v, &K); for(int i=1; i<=N; i++) scanf("%d", &V[i]); for(int i=1; i<=N; i++) { scanf("%d", &W[i]); } memset(f, 0, sizeof(f)); for(int i=1; i<=N; i++) { for(int j=v; j>=0; j--) { int Aln=0, Bln=0; for(int kk=0; kk<K; kk++) { if(j >= W[i]) A[Aln++] = f[j-W[i]][kk]+V[i]; //选 B[Bln++] = f[j][kk]; //不选 } //printf("A: "); //print(A, 0, Aln-1); //printf("B: "); //print(B, 0, Bln-1); int An=0, Bn=0; int c = 0; while(c < K && An<Aln && Bn<Bln) { if(A[An] > B[Bn]) f[j][c] = A[An++]; else f[j][c] = B[Bn++]; if(c==0 || (c>0&&f[j][c]!=f[j][c-1])) c++; } while(c < K && An<Aln) f[j][c++] = A[An++]; while(c<K && Bn<Bln) f[j][c++] = B[Bn++]; //printf("unite: "); //print(f[j], 0, K-1); } } printf("%d\n", f[v][K-1]); //答案是f[v][k-1] } return 0; }
时间: 2024-10-13 00:11:07