文章目录

  • 题目分析
  • 题目链接

题目分析

分析
把N(样例中N=169)看成背包的体积;把k(样例中k=5)看成背包能承的重量。把这道题转化为二维完全背包问题。由于数据范围给出的次幂P∈[2,7],那么p取2的时候,会使得数的个数最多,对应到背包问题,就是物品的数量最多,此时最多是20个物品。因为N最大是400。

对于每个物品,有两个属性:体积和重量
下面的p是次幂,如果是平方,则p=2.

物品序号 体积 重量 价值 = 物品序号
1 1p1^p1p 1 1
2 2p2^p2p 1 2
iii ipi^pip 1 iii
20 20p20^p20p 1 20

问题重述:

给定背包体积为N,背包能装的最大重量为K;

物品序号i从1开始,其价值等于序号;每个物品体积为ipi^pip,每个物品的重量都是1.且每个物品可以用无限次。

求恰好把背包装满,价值之和最大的方案。

下面是dp的分析
状态表示:

f[i][j][k]f[i][j][k]f[i][j][k]表示所有只考虑前i个物品,使得总p次方之和(总的体积)为j,且物品的个数恰好为k 的选法的价值。

状态计算:
对于第i个物品,有很多种选择:可以1个都不选,可以选1次,2次,…,很多次。

状态转移方程(结论)
f[i][j][k]=max(f[i−1][j][k],f[i][j−ip][k−1]+i)f[i][j][k] =max(f[i-1][j][k],f[i][j-i^p][k-1]+i)f[i][j][k]=max(f[i−1][j][k],f[i][j−ip][k−1]+i)

下面是具体的推导过程,不想看的话可以直接用这个状态转移方程。

如果1个都不选,那价值就是f[i−1][j][k]f[i-1][j][k]f[i−1][j][k];
如果 选1个的话,那价值就是f[i−1][j−ip][k−1]+i×1f[i-1][j-i^p][k-1]+i\times 1f[i−1][j−ip][k−1]+i×1;
如果选 s个话,价值就是f[i−1][j−ip×s][k−s]+i×sf[i-1][j-i^p\times s][k-s]+i \times sf[i−1][j−ip×s][k−s]+i×s.

所以,状态转移就是其中的最大值:
f[i][j][k]=max(f[i−1][j][k],f[i−1][j−ip][k−1]+i,...,f[i−1][j−ip×s][k−s]+i×s,...)(1式)f[i][j][k] =max(f[i-1][j][k],f[i-1][j-i^p][k-1]+i,...,f[i-1][j-i^p\times s][k-s]+i \times s,...)\ (1式)f[i][j][k]=max(f[i−1][j][k],f[i−1][j−ip][k−1]+i,...,f[i−1][j−ip×s][k−s]+i×s,...) (1式)

但是状态可以化简令j=j−ip,k=k−1j =j-i^p,k=k-1j=j−ip,k=k−1,得到下式:

f[i][j−ip][k−1]=max(f[i−1][j−ip][k−1],f[i−1][j−2ip][k−2]+i,...,f[i−1][j−ip×s][k−s]+i×s,...)(2式)f[i][j-i^p][k-1] =max(f[i-1][j-i^p][k-1],f[i-1][j-2i^p][k-2]+i,...,f[i-1][j-i^p\times s][k-s]+i \times s,...)\ (2式)f[i][j−ip][k−1]=max(f[i−1][j−ip][k−1],f[i−1][j−2ip][k−2]+i,...,f[i−1][j−ip×s][k−s]+i×s,...) (2式)

经过对比,1式可以用2式表示,1式max中从第二项开始和2式一一对应,只不过每一项多i,所以将而是带入1式,得:
f[i][j][k]=max(f[i−1][j][k],f[i][j−ip][k−1]+i)f[i][j][k] =max(f[i-1][j][k],f[i][j-i^p][k-1]+i)f[i][j][k]=max(f[i−1][j][k],f[i][j−ip][k−1]+i)

上面就是状态转移的公式。其实和完全背包的状态转移的分析思路一致,如有兴趣,请移步:完全背包dp优化

dp过程的具体代码实现


//三维:需要三重for循环int i;//枚举所有的物品for( i=1; ; i++){int v = power(i ,p);// 物品i的体积:i的p次方if(v > n) break; //背包体积n,已经装不下for(int j = 0; j <= n; j++) //枚举f的第二维 (背包体积):和为nfor(int  k =0; k<= K; k++) //枚举f的第三维(背包承的重量):数的个数{f[i][j][k] = f[i-1][j][k];//如果f[i][j-v][k-1]合法的话,就转移if( j>= v && k)f[i][j][k] = max(f[i][j][k], f[i][j-v][k-1]+i);}}//退出for循环的条件是第一个不符合的i,所以合法的应该i-1i--;

ac代码

#include<bits/stdc++.h>
using namespace std;
const int N = 410;int f[21][N][N]; //21个物品,后面是两维背包限制:体积和重量(分别是p次方之和,个数)
int n, K, p;//计算a的b次方,用来求i的p次方
int power(int a, int b){int res =1;while(b--) res *= a;return res;
}
int main(){cin >> n >> K >> p;memset(f ,-0x3f, sizeof f); //初始化为负无穷,表示不存在f[0][0][0] = 0; //初始条件,一个物品都没有,价值为0int i;//枚举所有的物品for( i=1; ; i++){int v = power(i ,p);// 物品i的体积:i的p次方if(v > n) break; //背包体积n,已经装不下for(int j = 0; j <= n; j++) //枚举f的第二维for(int  k =0; k<= K; k++) //枚举f的第三维:数的个数{f[i][j][k] = f[i-1][j][k];//如果f[i][j-v][k-1]合法的话,就转移if( j>= v && k)f[i][j][k] = max(f[i][j][k], f[i][j-v][k-1]+i);}}//退出for循环的条件是第一个不符合的i,所以合法的应该i-1i--;if(f[i][n][K] < 0) cout<<"Impossible";//下面是倒序输出具体方案:else{cout<<n<<" = ";bool is_first = true; //用来控制输不输出加号//找方案:倒推,看怎么转移过来的,i选没选?选的话就输出while(i){int v = power(i, p); //体积//正推:如果选i价值大则选i。反过来,如果选i价值大,代表已经选过,应该输出。// >= 左边代表选择i,右边代表不选i//之所有用while,不用if,是因为i可以选择多次while(f[i][n-v][K-1] + i >=  f[i-1][n][K]){if(is_first) is_first  =false;else cout<<" + ";printf("%d^%d",i,p);     //i的p次方   n -= v ,K--; //体积--,数量--}i--; //i处理完了,倒退看看前面的选没选}}}

题目链接

PAT甲级1103 Integer Factorization (30 分)
https://www.acwing.com/problem/content/1595/

PAT甲级1103 Integer Factorization (30 分):[C++题解]背包问题,DP解法相关推荐

  1. PAT甲级 -- 1103 Integer Factorization (30 分)

    The K−P factorization of a positive integer N is to write N as the sum of the P-th power of K positi ...

  2. 1103 Integer Factorization (30分)

    第一个深度优先搜索的题目. 很显然这个就是分情况讨论,每次选和不选某值,最终将满足结果的序列筛选出来,我自己写的一个dfs遍历,我比较喜欢对每一个元素进行遍历,用循环控制,这样的好处是避免递归层数太多 ...

  3. 1103 Integer Factorization (30 分)【难度: 中 / 爆搜】

    https://pintia.cn/problem-sets/994805342720868352/problems/994805364711604224 爆搜的做法,动态规划也可以做,有时间也一个动 ...

  4. PAT甲级1072 Gas Station (30 分):[C++题解]dijkstra算法、最短路

    文章目录 题目分析 题目来源 题目分析 来源:acwing 分析: 所有的dist[ ]都≤Ds:最小的dist[ ]最大; dist[ ] 总和最大. 由于加油站是字符,为了简单起见,将m个加油站编 ...

  5. PAT甲级1155 Heap Paths (30 分):[C++题解]堆、堆的遍历、树的遍历、dfs输出路径、完全二叉树建树

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 堆首先是完全二叉树,所以先建完全二叉树,由于给定的是层序遍历的数据,所以直接用数组即可,注意数组下标从1开始,这样便满足结点u和左儿 ...

  6. PAT甲级1107 Social Clusters (30 分):[C++题解]并查集,爱好、人数

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 凭爱好,分人群.注意点:爱好可传递.什么意思?意思是A和B的有共同爱好1, B和C有共同爱好2,那么认为A和C也是同一群人. 按照爱 ...

  7. PAT甲级1049 Counting Ones (30 分):[C++题解]统计1的个数、数位统计

    文章目录 题目分析 题目链接 题目分析 来源:PAT网站 分析: 以数字abcdefg这个7位数字为例,说一下本题的思路. 1)数字1在每一位出现的次数. 2)以第d位为例,第d位的取值可以分为3种情 ...

  8. PAT甲级1139 First Contact (30 分):[C++题解] 图论、暴力枚举两个点、hash映射

    文章目录 题目分析 题目链接 题目分析 来源:acwing 题目分析: 图论模拟题. 给定暗恋的两个人A 和B,需要寻找一对C 和D ,满足:A和C是朋友,C和D是朋友,D和B是朋友.而且A.C同性别 ...

  9. PAT甲级1131 Subway Map (30分):[C++题解]堆优化dijkstra、单源最短路、地铁地图、巧妙地建图套dijkstra模板!!

    文章目录 题目分析 题目链接 题目分析 原题: 来源:acwing 分析: 建图:所有能走到的点之间建立一条边,比如下面一条地铁线路有4站,它们是相通的,两两之间建一条边,边权是经过的站点数. 下面考 ...

最新文章

  1. 用TLS搭建即时通讯的安全通道:LCS2005系列之三
  2. Spring-----projects-----概述
  3. 数据结构 判断单链表是否有环 C
  4. 制作类似QQ截图软件
  5. .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理
  6. Spring Boot 数据国际化
  7. python flask实战视频_Python Flask打造一个视频网站实战视频教程
  8. android 工程搭建,Android ApiDemo示例工程的创建
  9. 第二阶段冲刺第八天(6月7号)
  10. 挑战程序员同学,如何只用2GB内存从20/40/80亿个整数中找到出现次数最多的数?
  11. 零基础入门深度学习(2) - 线性单元和梯度下降
  12. Java LinkedList – Java中的LinkedList
  13. websphere一直安装部署_构建独立部署系统,从部署规范开始
  14. mx250显卡天梯图_mx250显卡天梯图_2020年最新笔记本显卡天梯图,看看你的显卡排在哪!...
  15. ps存不了psd格式怎么办_ps打不开psd文件怎么办
  16. 什么是OA系统?OA系统是什么?OA是什么意思?
  17. des 加密 iOS
  18. 洛谷 P1948 [USACO08JAN]电话线Telephone Lines【NOIP模拟笨笨的电话线】
  19. Android工程师未来发展方向以及薪资待遇
  20. SolarWinds入侵事件余波:英特尔、英伟达、思科等科技巨头亦躺枪

热门文章

  1. MySQL xtrabackup之--databases 勿手贱
  2. FreeRTOS知识点
  3. 5月26 留言板练习题
  4. Java调用Oracle存储Package
  5. 各模组相关interface
  6. 5分钟安全顾问 - 针对家庭办公室用户的简单防火墙安装
  7. python和docker交互_jupyter notebook 连接服务器docker中python环境
  8. java类获取声明,获取用于MethodInvocation的实际类而不是声明类 - java
  9. 5.10 程序示例--模型选择-机器学习笔记-斯坦福吴恩达教授
  10. 玩转Mixly – 5、Arduino AVR编程 之 逻辑