获取中...

-

Just a minute...

0-1背包

一.01背包

划重点:当一件物品只能用一次时,必须要在同一个背包循环中只放一次,所以要容量倒走,根据递推表达式也可以知道

例题1:

https://www.luogu.org/problemnew/show/P1060

普通版:

每件物品之能拿一次,有拿和不拿俩种状态

dp(i,j)表示拿到i件物品时,j容量下价值的最大值

空间够用:判断价值决定拿不拿 dp[j][i] = max(dp[j-1][i],dp[j-1][i - th[j].m]+th[j].m*th[j].v);

空间不够用:只有不拿 dp[j][i] = dp[j-1][i];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*-------------------------------------------------------------------------------------------*/
struct BAG
{
int m;
int v;
}th[25];
int dp[25][MAX];
/* ------------------------------------------------------------------------------------------*/

int main()
{
//std::ios::sync_with_stdio(false);
cin >> M >> N;
for(int i =1;i <= N;i++)
{
cin >> th[i].m >> th[i].v;
}
for(int j = 1;j <= N;j++)
{
for(int i = 1;i <= M;i++)
{
if(th[j].m <= i)
{
dp[j][i] = max(dp[j-1][i],dp[j-1][i - th[j].m]+th[j].m*th[j].v);
}
else
{
dp[j][i] = dp[j-1][i];
}
}
}
cout << dp[N][M] << "\n";
return 0;
}
优化空间:

(不是这个题的,只是空间优化了,没有加权值而已,一毛一样)

https://www.luogu.org/problemnew/show/P1049

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*-------------------------------------------------------------------------------------------*/
int a[MAX_1];
int dp[MAX];
/* ------------------------------------------------------------------------------------------*/

int main()
{
//std::ios::sync_with_stdio(false);
cin >> M >> N;
for(int i = 0;i <= MAX;i++)
{
dp[i] = i;
}
for(int i =1;i <= N;i++)
{
cin >> a[i];
}
for(int j = 1;j <= N;j++)
{
for(int i = M;i >= 1;i--)
{
if(a[j] <= i)
{
dp[i] = min(dp[i],dp[i-a[j]]);
//cout << i << ":" << dp[i-a[j]] << " " << dp[i] <<endl;
}
}
}
cout << dp[M] << "\n";
return 0;
}

例题2:

https://www.luogu.org/problemnew/show/P1164

这个题需要背包恰好装满

把dp初始化为INF,当 当前的物品不能恰好装满的时候,就为非法值

dp[i]存储的为,背包容量为i的时候恰好装满的方案数,不存在为INF

dp[0] = 1;递推;

1.装不下不装

2.装下但不是恰好装满,不装

3.恰好装满

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*-------------------------------------------------------------------------------------------*/
int a[MAX_1];
int dp[MAX];
/* ------------------------------------------------------------------------------------------*/

int main()
{
//std::ios::sync_with_stdio(false);
cin >> N >> M;
for(int i = 1;i <= MAX;i++)
{
dp[i] = INF;
}
dp[0] = 1;
for(int i =1;i <= N;i++)
{
cin >> a[i];
}
//dp[a[1]] = 1;
for(int j = 1;j <= N;j++)
{
for(int i = M;i >= 1;i--)
{
if(a[j] <= i)
{
if(dp[i - a[j]] != INF)
{
if(dp[i] == INF)
{
dp[i] = dp[i - a[j]];
}
else dp[i] += dp[i - a[j]];

}
}
}
}
cout << dp[M] << "\n";
return 0;
}

此题有待寻找更好的递推

二.完全背包

容量正走

https://www.luogu.org/problemnew/show/P1616

没什么不同啊,就是把容量正的走而已了,一件物品放一次放一次放一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*-------------------------------------------------------------------------------------------*/
struct YAO
{
int t;
int v;
}a[MAX_1];
int dp[MAX];
/* ------------------------------------------------------------------------------------------*/

int main()
{
//std::ios::sync_with_stdio(false);
cin >> M >> N;
for(int i =1;i <= N;i++)
{
cin >> a[i].t >> a[i].v;
}
for(int i = 1;i <= M;i++)
{
for(int j = 1;j <= N;j++)
{
if(a[j].t <= i)
{
dp[i] = max(dp[i],dp[i-a[j].t]+a[j].v);
}
}
}
cout << dp[M] << "\n";
return 0;
}

三.多重背包

听说是:三重循环

还没做题呢,等着吧

完全背包的恰好装满

多重背包的俩种没做

四.变形背包

https://www.luogu.org/problemnew/show/P1064

数据读入做了下处理,减少循环

使用了vector记录每个主件有几个附件

题意说了,最多俩个

dp[i]当然是最大的价值

那么我们的状态转移就有4个

一个主件

一主一副1

一主一副2

一主俩副

转移就完事了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*-------------------------------------------------------------------------------------------*/
struct YAO
{
int m;
int v;
YAO(int mm,int vv) : m(mm),v(vv){}
};
vector<vector<YAO> > a(MAX_1);
int dp[MAX];
/* ------------------------------------------------------------------------------------------*/

int main()
{
//std::ios::sync_with_stdio(false);
cin >> M >> N;
M /= 10;
for(int i =1;i <= N;i++)
{
int x,y,z;
cin >>x >>y>>z;
if(z == 0)
{
a[i].push_back(YAO(x/10,y));
}
else
{
a[z].push_back(YAO(x/10,y));
}
}

for(int i = 1;i <= N;i++)
{
if(a[i].size() == 0) continue;
for(int j = M;j >= 1;j--)
{
if(j >= a[i][0].m)
{
dp[j] = max(dp[j],dp[j - a[i][0].m]+a[i][0].m*a[i][0].v);
}
if(a[i].size() > 1)
{
if(j >= a[i][0].m + a[i][1].m)
{
dp[j] = max(dp[j],dp[j - a[i][0].m - a[i][1].m]+a[i][0].m*a[i][0].v+a[i][1].m*a[i][1].v);
}
if(a[i].size() > 2)
{
if(j >= a[i][0].m + a[i][2].m)
{
dp[j] = max(dp[j],dp[j - a[i][0].m - a[i][2].m]+a[i][0].m*a[i][0].v+a[i][2].m*a[i][2].v);
}
if(j >= a[i][0].m + a[i][1].m +a[i][2].m)
{
dp[j] = max(dp[j],dp[j - a[i][0].m - a[i][1].m - a[i][2].m]+a[i][0].m*a[i][0].v+a[i][2].m*a[i][2].v + a[i][1].m*a[i][1].v);
}
}
}
}
}
cout << dp[M]*10 << "\n";
return 0;
}
相关文章
评论
分享
  • 线性动态规划

    一.最长上升(下降)子序列https://www.luogu.org/problemnew/show/P1091 https://www.luogu.org/problemnew/show/P1020 P1091:让每一个人做最中间人...

    线性动态规划
  • CF-577-2

    Codeforces Round #577 (Div. 2)A.Important Exam问学生分数总和最大为多少 那么就是每道题选的最多的选项为答案,计算即可 B.Zero Array如果sum是奇数的一定不行 如果是偶数的话就看...

    CF-577-2
  • NC-5

    2019牛客暑期多校训练营(第五场)A.digits 2输出N个N即可 B.generator 1题目思路:平常这个脑子会比比赛时候好用很多 比赛时候看到数据范围也想到了有没有十进制快速幂这种操作,但是没想到怎么实现 牛客这个测评鸡真...

    NC-5
  • ECF-69-2

    Educational Codeforces Round 69 (Rated for Div. 2)A.DIY Wooden Ladder找最长的的俩个,然后看是能放的木板多,还是给的木板多 B.Pillars观察发现这个序列有三种情...

    ECF-69-2
  • NC-4

    2019牛客暑期多校训练营(第四场)A.meeting题目思路:看到就想到之前的换根dp,真的就可以 cfrerooting传送门 我们把他们要去的集合地点作为树根 然后dp[i]表示到达 i 节点需要的最长时间(树深度) 状态转移 ...

    NC-4
  • CF-575-3

    Codeforces Round #575 (Div. 3)A.Three Piles of Candies傻逼题,一人拿一堆,剩下一堆还能随便分,加起来除2 B.Odd Sum Segments一个序列里只有奇数个奇数时和才是奇数 ...

    CF-575-3
  • CF-574-2

    Codeforces Round #574 (Div. 2)A.Drinks Choosing就把可以凑对的凑在一起,不能的俩俩组合 B.Sport Mafia题目思路:算出全放糖果的sum,算出与留下糖果的差cha 可知,每少放一次...

    CF-574-2
  • ECF-67.2

    题目传送门 A:Stickers and Toys三种情况,没有重叠,有重叠,都重叠 B:Letters Shop开个二维数组,记录每一种字母的位置 扫描字符串找到位置最靠后的字母 C:Vasya And Array题解的方法还没搞懂...

    ECF-67.2
  • 专题-搜索

    专题-搜索
  • vim

    vim
Please check the parameter of comment in config.yml of hexo-theme-Annie!