【动态规划】【归并】Vijos P1412 多人背包

题目链接:

  https://vijos.org/p/1412

题目大意:

  求01背包的前K优解,要求必须装满(1<=K<=50 0<=V<=5000 1<=N<=200)

题目思路:

  【动态规划】

  f[j][k]表示花费为j的第k优解。

  合并的过程用归并。

 1 //
 2 //by coolxxx
 3 ////<bits/stdc++.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<string>
 7 #include<iomanip>
 8 #include<memory.h>
 9 #include<time.h>
10 #include<stdio.h>
11 #include<stdlib.h>
12 #include<string.h>
13 //#include<stdbool.h>
14 #include<math.h>
15 #define min(a,b) ((a)<(b)?(a):(b))
16 #define max(a,b) ((a)>(b)?(a):(b))
17 #define abs(a) ((a)>0?(a):(-(a)))
18 #define lowbit(a) (a&(-a))
19 #define sqr(a) ((a)*(a))
20 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
21 #define mem(a,b) memset(a,b,sizeof(a))
22 #define eps (1e-8)
23 #define J 10
24 #define MAX 0x7f7f7f7f
25 #define PI 3.14159265358979323
26 #define N 204
27 #define M 5004
28 #define K 54
29 using namespace std;
30 typedef long long LL;
31 int cas,cass;
32 int n,m,lll,ans;
33 int v[N],c[N],t[K<<1];
34 int f[M][K];
35 void merge(int a[],int b[],int c)
36 {
37     int i,j,k;
38     for(i=1,j=1,k=0;i+j<=cas+1;)
39     {
40         if(a[i]>b[j]+c)t[++k]=a[i++];
41         else t[++k]=b[j++]+c;
42     }
43     while(i<=cas)t[++k]=a[i++];
44     while(j<=cas)t[++k]=b[j++]+c;
45     for(i=1;i<=cas;i++)a[i]=t[i];
46 }
47 int main()
48 {
49     #ifndef ONLINE_JUDGE
50 //    freopen("1.txt","r",stdin);
51 //    freopen("2.txt","w",stdout);
52     #endif
53     int i,j;
54 //    for(scanf("%d",&cas);cas;cas--)
55 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
56 //    while(~scanf("%s",s))
57     while(~scanf("%d",&cas))
58     {
59         mem(f,-0x7f);mem(t,-0x7f);ans=0;
60         scanf("%d%d",&m,&n);
61         for(i=1;i<=n;i++)
62         {
63             scanf("%d%d",&v[i],&c[i]);
64         }
65         f[0][1]=0;
66         for(i=1;i<=n;i++)
67         {
68             for(j=m;j>=v[i];j--)
69             {
70                 merge(f[j],f[j-v[i]],c[i]);
71             }
72         }
73         for(i=1;i<=cas && f[m][i]>0;i++)ans+=f[m][i];
74         printf("%d\n",ans);
75     }
76     return 0;
77 }
78 /*
79 //
80
81 //
82 */

时间: 2024-12-28 11:19:25

【动态规划】【归并】Vijos P1412 多人背包的相关文章

P1858 多人背包

P1858 多人背包 题目描述 求01背包前k优解的价值和 要求装满 调试日志: 初始化没有赋给 dp[0] Solution 首先补充个知识点啊, 要求装满的背包需要初始赋 \(-inf\), 边界为 \(dp[0] = 0\) 第 \(k\) 优解的01背包 以 \(dp[j][k]\) 表示 容量为 \(j\) 的背包的第 \(k\) 优解 用到了归并排序的思想 对于第 \(i\) 个物品, 容量为 \(j\), 我们有两种选择: 选第 \(i\) 个物品 不选第 \(i\) 个物品 对于

[XJOI]noip43 T2多人背包

多人背包 DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包.这些包的容量是相同的,都是 V.可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值.在 DD 看来,合理的背包安排方案是这样的:1. 每个人背包里装的物品的总体积恰等于包的容量. 2. 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品. 3. 任意两个人,他们包里的物品清单不能完全相同. 在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢? 输入格式: 第一行有三个整数:K

vijos1412 多人背包

01背包+归并 看的题解  https://vijos.org/p/1412/solution #include<cstdio> #include<cstring> using namespace std; int a[205]; int b[205]; int f[5005][55]; int k,n,v; void work(int *aa,int *bb,int c) { int t[105]; int ti=1; int ai=1; int bi=1; while(ai+b

【动态规划】Vijos P1493 传纸条(NOIP2008提高组第三题)

题目链接: https://vijos.org/p/1493 题目大意: 二取方格数,从(1,1)向下或向右走到(n,m)走两次,每个走到的格子值只能被取一次所能取到的最大值. (n,m<=50) 题目思路: [动态规划] f[i][j][k][l]表示第一次走到(i,j)第二次走到(k,l)的最大值. 分别向上或向左转移. 1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #incl

【动态规划】Vijos P1011 清帝之惑之顺治

题目链接: https://vijos.org/p/1011 题目大意: 给一张N*M的地图(N,M<=500),可从任一点开始沿上下左右走,只能走比当前低的地方.问最长能走多少格. 题目思路: [动态规划] 这题就是滑雪,动态规划. 将高度排序后从低往高算,当前高度所在的格子上下左右比当前高度低就可以用来更新答案. 1 // 2 //by coolxxx 3 // 4 #include<iostream> 5 #include<algorithm> 6 #include&l

Vijos 1180 (树形DP+背包)

题目链接: https://vijos.org/p/1180 题目大意:选课.只有根课选了才能选子课,给定选课数m, 问最大学分多少. 解题思路: 树形背包.cost=1. 且有个虚根0,取这个虚根也要cost,所以最后的结果是dp[0][m+1]. 本题是cost=1的特殊背包问题,在两个for循环上有一个优化. for(f+1...j....cost) for(1....k...j-cost) 其中f为当前已经dfs子结点个数.之所以+1,是因为根要预留一个空间. f+=dfs(t),dfs

【动态规划】Vijos P1143 三取方格数

题目链接: https://vijos.org/p/1143 题目大意: NxN的矩阵,每个值只能取一次,从(1,1)走到(n,n)走三次能取得的最大值. 题目思路: [动态规划] f[x1][y1][x2][x3]表示第一次走x1,y1,相同步数下第二次走x2,y2,第三次走x3,y3的最大值. 因为步数一样y2,y3可以直接求出来. 1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #i

【动态规划】Vijos P1121 马拦过河卒

题目链接: https://vijos.org/p/1616 题目大意: 卒从(0,0)走到(n,m),只能向下或向右,不能被马一步碰到或走到马,有几种走法. 题目思路: [动态规划] 把马控制的地方全部标记,接下来DP,f[i][j]=f[i-1][j]+f[i][j-1]; 1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #inc

【动态规划】Vijos P1616 迎接仪式

题目链接: https://vijos.org/p/1616 题目大意: 长度为N的字符串,只含‘j’和‘z’,可以将任意两个字符调换K次,求能够拥有的最多的'jz'串. 题目思路: [动态规划] 首先相同字符是不用调换的,一个字符最多被调换一次(a<—>b,b<—>c等价于a<—>c) f[i][j][z]表示前i个字符,改变了j个'j'和z个'z'后的“jz”串数. 那么只考虑前两位,有四种情况(jj,jz,zj,zz)来转移. 注意初始化!!! 1 // 2 //