IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [01背包变形 二维费用]837 D. Round Subset -> 正文阅读

[数据结构与算法][01背包变形 二维费用]837 D. Round Subset

[01背包变形]837 D. Round Subset

题目

题目链接

题意
我们把一个数的 roundness 值定义为它末尾 0 的个数。
给你一个长度为 n 的数列,要求你从中选出 k 个数,使得这些选出的数的积的 roundness 值最大。也就是求 m a x { m i n ( ∑ c n t 2 , ∑ c n t 5 ) } max\{min(\sum{cnt_2},\sum{cnt_5})\} max{min(cnt2?,cnt5?)}

思路

末尾0的个数那就要统计2和5的个数,先预处理每个数能贡献多少2和5
选K个数容易想到01背包,接下来思考动态规划部分
原问题:一个长度为 n 的数列,要求你从中选出 k 个数,使得这些选出的数的积的 roundness 值最大。
子问题:一个长度为i的数列,要求你从中选出 j 个数,使得这些选出的数的积的 roundness 值最大。
尝试列出转移方程,令 f [ i ] [ j ] f[i][j] f[i][j]为答案数组, t w o [ i ] 为 第 i 个 数 因 子 2 数 量 two[i]为第i个数因子2数量 two[i]i2, f i v e [ i ] 为 第 i 个 数 因 子 5 数 量 five[i]为第i个数因子5数量 five[i]i5
不 选 当 前 数 f [ i ] [ j ] = f [ i ? 1 ] [ j ] 不选当前数f[i][j]=f[i-1][j] f[i][j]=f[i?1][j]
选 当 前 数 f [ i ] [ j ] = f [ i ? 1 ] [ j ? 1 ] + ( t w o [ i ] , f i v e [ i ] ) 选当前数f[i][j]=f[i-1][j-1]+(two[i],five[i]) f[i][j]=f[i?1][j?1]+(two[i],five[i])发现写不出来

为什么写不出状态转移方程?
思考一下历史状态信息+当前第i个物品的信息能不能推出新状态的信息
历史信息: f [ i ? 1 ] [ j ? 1 ] f[i-1][j-1] f[i?1][j?1]
告诉你状态 ( i , j ) (i,j) (i,j)下, m i n ( c n t 2 , c n t 5 ) = f [ i ? 1 ] [ j ? 1 ] min(cnt_2,cnt_5)=f[i-1][j-1] min(cnt2?,cnt5?)=f[i?1][j?1]
新加入物品信息: t w o [ i ] , f i v e [ i ] two[i],five[i] two[i],five[i]
告诉你新加入物品会使得 c n t 2 + t w o [ i ] cnt_2+two[i] cnt2?+two[i]以及 c n t 5 + f i v e [ i ] cnt_5+five[i] cnt5?+five[i]
但是我们现在只知道 m i n ( c n t 2 , c n t 5 ) min(cnt_2,cnt_5) min(cnt2?,cnt5?),我们没法通过新加入物品的信息得到 m i n ( c n t 2 + t w o [ i ] , c n t 5 + f i v e [ i ] ) min(cnt_2+two[i],cnt_5+five[i]) min(cnt2?+two[i],cnt5?+five[i])
那么这种情况我们要考虑维护新的信息

考虑维护新的信息
如果我们知道每个状态的 c n t 2 和 c n t 5 cnt_2和cnt_5 cnt2?cnt5?那我们就可以很容易的推出新状态了,我们添加两个维度用来记录 c n t 2 和 c n t 5 cnt_2和cnt_5 cnt2?cnt5?
可以得到选第i个物品的状态转移
f [ i ] [ j ] [ p ] [ q ] = f [ i ] [ j ] [ p ? t w o [ i ] ] [ q ? f i v e [ i ] ] + m i n ( p , q ) f[i][j][p][q]=f[i][j][p-two[i]][q-five[i]]+min(p,q) f[i][j][p][q]=f[i][j][p?two[i]][q?five[i]]+min(p,q)
但是考虑p和q范围,1<=ai<=1e18,单个数two[i]上限为60左右,five[i]上限为26左右,这有200个数,时空双爆炸,螺旋升天。

考虑可不可以把其中一个维度扔出来作为dp的含义
尝试把 c n t 2 cnt_2 cnt2?扔出来作为dp的含义
g [ i ] [ j ] [ p ] g[i][j][p] g[i][j][p]表示前i个中选j个且他们的积有p个因子5的情况下,最多可以有多少个2
状态转移方式
不选第i个 g [ i ] [ j ] [ p ] = g [ i ? 1 ] [ j ] [ p ] g[i][j][p]=g[i-1][j][p] g[i][j][p]=g[i?1][j][p]
选第i个 g [ i ] [ j ] [ p ] = m a x ( g [ i ] [ j ] [ p ] , g [ i ? 1 ] [ j ? 1 ] [ p ? f i v e [ i ] ] + t w o [ i ] ) g[i][j][p]=max(g[i][j][p],g[i-1][j-1][p-five[i]]+two[i]) g[i][j][p]=max(g[i][j][p],g[i?1][j?1][p?five[i]]+two[i])
初始值:默认为负无穷,g[1][0][0]=0(因为这题恰好)
最后遍历一遍取max{min(p,q)}就行了
进步优化可以压掉第一个维度,类似01背包压掉一维度

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
int n,m,ans,tmp;
int a[210],cnt2[210],cnt5[210];
int dp[210][20000];
//设dp[i][j]表示选i个物品,5有j个时2的最多数量。
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        tmp=a[i];
        while(tmp%2==0)
            cnt2[i]++,tmp/=2;
        while(tmp%5==0)
            cnt5[i]++,tmp/=5;
    }
    memset(dp,0xcf,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
            for(int k=10000;k>=cnt5[i];k--)
                dp[j][k]=max(dp[j][k],dp[j-1][k-cnt5[i]]+cnt2[i]);
    for(int i=0;i<=10000;i++)
        ans=max(ans,min(i,dp[m][i]));
    printf("%lld",ans);
    return 0;   
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-05 11:17:27  更:2021-09-05 11:19:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:13:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码