博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DP:Coins(POJ 1742)
阅读量:5145 次
发布时间:2019-06-13

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

                  

                  

  题目大意:就是有面值为A1,A2,A3....的硬币,各有C1,C2,C3...的数量,问在钱数为m的范围内,能换多少钱?(不找零)

  这题看名字就知道是完全背包,但是这题又有点不一样,因为这题的硬币数不是无限的,所以我们要用点特殊的思路

  因为这题要我们求的是可以整换的钱的面值数,我们只要保证位置合法就可以了,所以dp矩阵内我们可以以面值数的剩余量为dp量,对于j<面值的位置,我们全部设置为当前面值的硬币数量,当j>=面值时,我们考虑两个位置:1:当上一个位置的这个位置合法(也就i-1面值的剩余硬币数>=0),那我们把dp[i][j]位置设置成当前硬币面值的总数(这个是贪心的思想,我们总是想把钱换更大的面值),

  如果dp[i-1][j]非法,那我们就往dp[i][j-coins[i-1]]的位置考量,如果dp[i][j-coins[i-1]]位置还有硬币剩余,那这个位置就dp[i][j-coins[i-1]]-1就好了,因为我们可以拿多一个硬币换出这个面值。

  然后如果dp[i][j-coins[i-1]]非法,那dp[i][j]这个位置自然也就非法了。

  最后再回头看一下上面的思路,我们发现我们只要一个一维数组就行了,因为对于k<j的位置,我们总是先考虑了,而且dp[i-1][j]我们只使用一次

 

  最后这题排一次序速度会快一点,数量比较小,直接插入排序就好了,复杂度O(n*m)

  最后吐槽一下自己,这一题wa了好几次,因为我一直把上一个位置考虑错了,本来应该考察dp[i-1][j]的,

   结果变成dp[i-1][j-coins[i-1]]

  

1 #include 
2 #include
3 #include
4 #define MAX(a,b) (a)>(b)?(a):(b) 5 6 typedef struct coins_set 7 { 8 int coins_value; 9 int coins_sum;10 }SET;11 12 SET coins[101];13 int dp[100001];14 15 void Search(const int, const int);16 17 void Insertion_Sort(const int n)18 {19 int i, j, tmp_v, tmp_s;20 for (i = 2; i <= n; i++)21 {22 tmp_v = coins[i].coins_value;23 tmp_s = coins[i].coins_sum;24 for (j = i; j > 1 && coins[j - 1].coins_value > tmp_v; j--)25 {26 coins[j].coins_value = coins[j - 1].coins_value;27 coins[j].coins_sum = coins[j - 1].coins_sum;28 }29 coins[j].coins_value = tmp_v;30 coins[j].coins_sum = tmp_s;31 }32 }33 34 int main(void)35 {36 int n, m, i;37 while (~scanf("%d%d", &n, &m))38 {39 if (n == 0 && m == 0)40 break;41 //读取钱的总量42 for (i = 1; i <= n; i++)43 scanf("%d", &coins[i].coins_value);44 for (i = 1; i <= n; i++)45 scanf("%d", &coins[i].coins_sum);46 Insertion_Sort(n);47 Search(n, m);48 }49 return 0;50 }51 52 void Search(const int n, const int m)53 {54 int i, j, ans = 0;55 56 memset(dp, -1, sizeof(dp));57 for (i = 1; i <= coins[1].coins_sum; i++)//处理基准状态58 {59 if (i*coins[1].coins_value <= m)60 dp[i*coins[1].coins_value] = coins[1].coins_sum - i;61 else break;62 }63 dp[0] = coins[1].coins_value;64 for (i = 2; i <= n; i++)65 {66 dp[0] = coins[i].coins_value;67 for (j = 0; j <= m; j++)68 {69 if (j - coins[i].coins_value < 0)70 dp[j] = dp[j] == -1 ? -1 : coins[i].coins_sum;71 else72 {73 if (dp[j] != -1)74 dp[j] = coins[i].coins_sum;75 else if (dp[j - coins[i].coins_value] > -1)76 dp[j] = dp[j - coins[i].coins_value] - 1;77 else78 dp[j] = -1;79 }80 }81 }82 for (i = 1; i <= m; i++)83 if (dp[i] > -1) ans++;84 printf("%d\n", ans);85 }

 

转载于:https://www.cnblogs.com/Philip-Tell-Truth/p/4828714.html

你可能感兴趣的文章
Python如何实现doc文件转换为docx文件?
查看>>
n个数的最小公倍数
查看>>
解决Android中No resource found that matches android:TextAppearance.Material.Widget.Button.Inverse问题...
查看>>
xml合并问题,多个xml拼接
查看>>
20169220 <网络攻防实践> 第四周学习总结
查看>>
windows 下版本控制系统 安装与 配置
查看>>
计算机数值表示
查看>>
Seafile搭建私有云盘
查看>>
WCF自定义异常
查看>>
软件工程——团队作业2
查看>>
ceph osd 自动挂载的N种情况
查看>>
@RequestParam @RequestBody @PathVariable 等参数绑定注解详解
查看>>
spring配置文件详解
查看>>
poj 2318 计算几何
查看>>
[Java]-集合框架
查看>>
累了。
查看>>
JS 拼凑字符串
查看>>
hack
查看>>
c++学习笔记_2
查看>>
自我鉴定,继续努力
查看>>