博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cf837D(01背包)
阅读量:4636 次
发布时间:2019-06-09

本文共 1544 字,大约阅读时间需要 5 分钟。

题目链接:

 

题意: 给出 n 个数, 从中选出 k 个数使得这 k 个数的乘积末尾 0 最多 .

 

思路: 先记录每个数能分解出的 2 和 5 的数目, 然后弄个01背包即可 .

用 dp[i][j][l] 表示从前 i 个数中选出 j 的数其中 5 的个数为 l 个的情况下 2 的数目最多是多少 .

初始状态为 dp[0][0][0] = 0, 推到终态 dp[n][k][MAX] 即可 . 注意要存在上一种状态才能到达下一种状态 .

然而开三维会 mle, 可以优化一下空间, 去掉 i 这维 .

状态转移方程式: if(dp[j - 1][l - gel[i].y] != -1) dp[j][l] = max(dp[j][l], dp[j - 1][l - gel[i].y] + gel[i].x); //注意判断上一种状态是否存在

 

代码:

1 #include 
2 #include
3 #include
4 #define ll long long 5 using namespace std; 6 7 const int MAXN = 2e2 + 5; 8 const int MAX = 6e3; 9 struct node{10 int x, y;11 }gel[MAXN];12 13 int dp[MAXN][MAX];14 15 int main(void){16 ll x;17 int n, k, cnt = 0;18 cin >> n >> k;19 for(int i = 1; i <= n; i++){20 cin >> x;21 while(x % 2 == 0){22 gel[i].x += 1;23 x /= 2;24 }25 while(x % 5 == 0){26 gel[i].y += 1;27 x /= 5;28 cnt++;29 }30 }31 memset(dp, -1, sizeof(dp));32 dp[0][0] = 0;33 for(int i = 1; i <= n; i++){34 for(int j = k; j >= 1; j--){35 for(int l = gel[i].y; l <= cnt; l++){36 if(dp[j - 1][l - gel[i].y] != -1) dp[j][l] = max(dp[j][l], dp[j - 1][l - gel[i].y] + gel[i].x);37 }38 }39 }40 int sol = 0;41 for(int i = 1; i <= MAX; i++){42 sol = max(sol, min(i, dp[k][i]));43 }44 cout << sol << endl;45 return 0;46 }
View Code

 

转载于:https://www.cnblogs.com/geloutingyu/p/7286196.html

你可能感兴趣的文章
wp 删除独立存储空间文件(多级非空文件夹删除)
查看>>
Loadrunner安装使用入门
查看>>
smartupload 上传文件时 把页面编码改成gbk 解决乱码
查看>>
EPS是什么格式
查看>>
input禁止显示历史输入记录
查看>>
Python的数据库操作(Sqlalchemy)
查看>>
2.抽取代码(BaseActivity)
查看>>
My simplified pickit2 clone
查看>>
Redis 入门知识
查看>>
夏天过去了, 姥爷推荐几套来自smashingmagzine的超棒秋天主题壁纸
查看>>
转--Android如何在java代码中设置margin
查看>>
反射的所有api
查看>>
Js 判断网页窗口是否滚动到底部
查看>>
上传文件
查看>>
css 定位及遮罩层小技巧
查看>>
用java向mysql数据库中插入数据为空
查看>>
项目中非常有用并且常见的ES6语法
查看>>
dateTimePicker编辑状态下,取值不正确的问题
查看>>
mac 端口转发方案
查看>>
[2017.02.23] Java8 函数式编程
查看>>