博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3260 多重背包+完全背包
阅读量:7287 次
发布时间:2019-06-30

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

  前几天刚回到家却发现家里没网线 && 路由器都被带走了,无奈之下只好铤而走险尝试蹭隔壁家的WiFi,不试不知道,一试吓一跳,用个手机软件简简单单就连上了,然后在浏览器输入192.168.1.1就能看到他的路由器的一切信息,包括密码,然后打开笔记本……好了,废话不多说,能连上网后第一时间当然是继续和队友之前约好的训练了。

  今天翻看到之前落下的一道混合背包题目,然后在草稿本上慢慢地写递推方程,把一些细节细心地写好…(本来不用太费时间的,可是在家嘛,一会儿妈走来要我教她玩手机,一会儿有一个亲戚朋友来……简直无语了,程序猿最讨厌被人打断的!虽说我不是码农)然后,这道题,细心分析后,发现它是多重背包+完全背包的。

  首先,可以先顺着推出 John手中的coin能拼凑出的币值的最小币数,即设dp[i][j]为前 i 种coin凑出币值 j 时需要的最小币数,很明显,dp[i][j]= min(dp[i-1][j], dp[i][j-coin[i]]+1) 的递推方程很容易想到,但是,这个方程在使用前需要满足很多情况,具体的细节就看代码了(全部都进行了空间优化,其中need数组表示前 i 种coin凑出币值 j 需要的最小币数时,需要的coin[i]的数量),因为之前看过《挑战》中多重背包的实现,所以这个稍微变化一下也不是很难了。

  然后,到了收银员找币时的情况,因为题目中说了她会提供无限的零钱,所以此时就是完全背包了,注意好计算顺序即可:

1 #include
2 #include
3 #include
4 using namespace std; 5 typedef long long LL; 6 const int maxn= 10000; 7 8 int dp[maxn+3], coin[103],num[103], need[maxn+3]; 9 10 int main(){11 int n,t,i,j;12 while(~scanf("%d%d",&n,&t)){13 for(i=1; i<=n; ++i)14 scanf("%d",coin+i);15 for(i=1; i<=n; ++i)16 scanf("%d",num+i);17 memset(dp,-1,sizeof(dp));18 dp[0]= 0;19 for(i=1; i<=n; ++i){20 memset(need,0,sizeof(need));21 for(j=0; j<=maxn; ++j)22 if(j>=coin[i]&& dp[j-coin[i]]!= -1 && need[j-coin[i]]
dp[j-coin[i]]+1){24 dp[j]= dp[j-coin[i]]+1;25 need[j]= need[j-coin[i]]+1;26 }27 }28 }29 for(i=1; i<=n; ++i)30 for(j=maxn-coin[i]; j>=0; --j)31 if(dp[j+coin[i]]!= -1){32 if(dp[j]== -1) dp[j]= dp[j+coin[i]]+1;33 else dp[j]= min(dp[j],dp[j+coin[i]]+1);34 }35 printf("%d\n",dp[t]);36 }37 return 0;38 }
View Code

  因为一开始没用到need数组所以调试了一会儿,然后今早起来想了想发现昨晚写的need数组有问题,不知是数据弱还是怎么的也能过,改了下后提交发现:

  竟然排到了16名,第一次这么前。

  后来又想了想,dp数组如果用INF而不是-1来作为凑不出币值 j 的标记的话,代码会更简单一些:

1 #include
2 #include
3 #include
4 using namespace std; 5 typedef long long LL; 6 const int INF= 0x3fffffff; 7 const int maxn= 10000; 8 9 int dp[maxn+3], coin[103],num[103], need[maxn+3];10 11 int main(){12 int n,t,i,j;13 while(~scanf("%d%d",&n,&t)){14 for(i=1; i<=n; ++i)15 scanf("%d",coin+i);16 for(i=1; i<=n; ++i)17 scanf("%d",num+i);18 for(j=1; j<=maxn; ++j)19 dp[j]= INF;20 dp[0]= 0;21 for(i=1; i<=n; ++i){22 memset(need,0,sizeof(need));23 for(j=0; j<=maxn; ++j)24 if(j>=coin[i] && need[j-coin[i]]
dp[j-coin[i]]+1){26 dp[j]= dp[j-coin[i]]+1;27 need[j]= need[j-coin[i]]+1;28 }29 }30 }31 for(i=1; i<=n; ++i)32 for(j=maxn-coin[i]; j>=0; --j)33 dp[j]= min(dp[j],dp[j+coin[i]]+1);34 printf("%d\n",dp[t]==INF? -1:dp[t]);35 }36 return 0;37 }
View Code

  虽然比起上一个慢了点可以忽略不计的时间:

  anyway,人生第一道AC掉的混合背包,值得纪念,背包问题,继续进取中~~

转载于:https://www.cnblogs.com/Newdawn/p/4269014.html

你可能感兴趣的文章
DAS、NAS、SAN、iSCSI 存储方案概述
查看>>
为VMware esxi主机配置系统日志记录
查看>>
给批量用户设磁盘配额
查看>>
Docker常见问题总结(持续更新)
查看>>
5-6单元练习
查看>>
以普通用户启动的Vim如何保存需要root权限的文件
查看>>
客户端和浏览器都不能连接SVN服务器
查看>>
计划任务
查看>>
华为交换机的命令行
查看>>
限制你的指令只能通过特定的方式来调用
查看>>
男神的补习
查看>>
while数字死循环
查看>>
备份架构——三种基本备份拓扑
查看>>
关于visual assist x插件不能用的解决方案
查看>>
Linux iptables:规则组成
查看>>
HDU 4442 Physical Examination【水题】【思维题】
查看>>
NET 命令 常用方法!
查看>>
我的友情链接
查看>>
memcached
查看>>
谁搞死了你的软件?
查看>>