• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
 






tim11

 
 

Powered by 博客园
博客园 | 首页 | 新随笔 | 联系 | 订阅 订阅 | 管理

随笔分类 -  背包问题

是dp,更是dp中的dp
 
poj 2923 (Relocation)(状态压缩dp)
摘要:http://poj.org/problem?id=2923(1)2辆车搬运n件家具,求最少的搬运次数。背包问题的一般思路是,把物品顺次装入背包,不过背包有且仅有一个。然而,这里的“背包”,不仅有两个, (2辆车),而且“背包”还可以重复使用。。。这种情况下,就不能简单地讲车看做背包,而应该另辟新径。(2)用到状态压缩(将每种状态用一个整数 x 的二进制形式来表示),先确定所有的状态下哪些情况能够一次运完,做好标记。在初始化dp数组为无穷大后 (dp[0]=0),遍历每种一次可以运完的情况,看看是否可以用它来更新其他状况的dp:if(!(j&re[i])) dp[j|re[i]]=.. 阅读全文
posted @ 2012-08-25 18:27 tim11 阅读(246) 评论(0) 推荐(0)
poj 2486 Apple Tree(树形dp+背包+dfs)(*****)
摘要:http://poj.org/problem?id=2486(1)本题属于只是交叉的题目,核心思想在于递归(状态转移方程的写出),假如要求得 p 点的信息,则可以通过其所有的相邻的点 now 的信息来更新。 而 now 的信息可以由未访问且与它相邻的点的信息来更新。(2)由于是树状结构,访问时可能会折回某一个点,然后去另一条支路上,所以走 K 步有返回起点和不返回起点两种形式。(3)最核心的算法本质:dp[0][g][i+j+2]=max(dp[0][g][i+j+2], dp[0][g][i]+dp[0][now][j]);dp[1][g][i+j+1]=max(dp[1][g][i+j+1 阅读全文
posted @ 2012-08-25 16:00 tim11 阅读(174) 评论(0) 推荐(0)
hdu 2546 饭卡 (01背包+贪心)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2546(1) 简单的01背包问题,但是只要有5元钱就可以买菜,不论菜多贵(但是才只能一样一样地买)。所以预留5元钱买最贵的菜。(2)排序时用到了:sort(a, a+n); 但是对于我的解法而言,应当是:sort(a+1, a+n+1);(3)有再循环里头用过一个 if-else 结构,并没有用贪心策略,AC了。可是代码丢了,也忘了时怎么写的。。(4)钱不够5元的直接输出结果。View Code #include<stdio.h>#include<string.h>#include&l 阅读全文
posted @ 2012-08-17 18:52 tim11 阅读(176) 评论(0) 推荐(0)
hdu 3449 Consumer(分组背包变形)**
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=3449(1)本题属于分组背包的类型,但对于每一组,需先买盒子才能买物品,盒子无价值,武平才有价值(其实盒子有价值也能做)。 如何保证买入物品时已经买入了盒子,且不会出现多次买同一个盒子的悲剧呢?有一种办法是,开一个新的数组d[100100],对于每个d[i], 先买下盒子 i, 再用剩余的钱继承原有的规划结果:for(j=p;j<=w;j++) d[j]=dp[j-p]; 然后一一装入该组各个物品,得到最优的 d[i] ,最后用来更新 dp[i] 。(2)用来买盒子的钱不可用:if(d[k-c]!=-1 阅读全文
posted @ 2012-08-17 15:47 tim11 阅读(284) 评论(0) 推荐(0)
poj 1787 Charlie's Change (多重背包+记录路径)***
摘要:http://poj.org/gotoproblem?pid=1787(1)本题为一般的多重背包问题,亮点在于记录路径的方法,开了一个数组 pre[10010] 记录前一步的位置。调用时用 sum[30] 逐个累加即可(当然,这里的调用方法还有其他的各种方法)。 记录:pre[j]=j-b[i]; 调用:for(i=m;pre[i]!=-1;i=pre[i]) ans[i-pre[i]]++;(2)多重背包一如既往,用数组 used[10010] 限制,转化为01背包(或是完全背包,只是形式有点像而已,不属于而这任何一类)。(3)初始化问题: 1)将dp[i] 预处理为0。 dp... 阅读全文
posted @ 2012-08-17 15:16 tim11 阅读(216) 评论(0) 推荐(0)
poj 1742 Coins (多重背包)
摘要:http://poj.org/gotoproblem?pid=1742(1)多重背包的处理方式有两种: 1)转化为分组背包。本题用到了将硬币数转化成“1,2,4,8,... ,余数”的形式。2)转化为01背包。再开一个数组,记录每一个dp[i] 对每一种硬币的使用情况,以确保不多用硬币。(2)以运行效率而言,上一条中2)的效率高一些(我的代码前者超时,后者AC,具体原因不是特别明确)。似乎本题就是在卡时间,在时间细节设陷阱,各位请注意。 以下代码用的是转化为01背包。具体代码:View Code #include<stdio.h>#include<string.h>#i 阅读全文
posted @ 2012-08-17 10:25 tim11 阅读(152) 评论(0) 推荐(0)
poj 3260 The Fewest Coins(多重背包+完全背包)
摘要:http://poj.org/gotoproblem?pid=3260(1)多重背包的处理方式:转化为分组背包(1,2,4,8,余数)。具体细节参见代码:scanf("%d", &num[i]);tn=num[i];while(tn>0){ if(tn<x) {map[i][tot++]=tn;break;} map[i][tot++]=x; tn-=x; x*=2;}(2)接下来是装多重背包,注意细节 for(j=0;map[i][j];j++) 而不是 for(j=1;map[i][j];j++) 进而用万群被白调整,注意循环顺序:for(k=V-m 阅读全文
posted @ 2012-08-16 21:05 tim11 阅读(149) 评论(0) 推荐(0)
poj 2063 Investment(01背包变形)
摘要:http://poj.org/gotoproblem?pid=2063(1)上限 m 一直上升的 n 次01背包问题,比一般的01背包多了一重循环;(2)本题出现了各种错误:1)刚开始,没注意 m 变大会影响 dp 的上限,开了个dp[1100000], RE; 2)由于 m 的只比较大, 开了个dp[8000000],MLE(内存不够); 3)改小为dp[5000000], TLE(超时); 4)为什么要开这么大数组,好像是因为 m 太大了。。 重新读题, The value of a bond is alway... 阅读全文
posted @ 2012-08-16 19:56 tim11 阅读(167) 评论(0) 推荐(0)
poj 1252 Euro Efficiency (01背包变形)
摘要:http://poj.org/gotoproblem?pid=1252(1)不是单纯的01背包问题,硬币有去有回(即有正有负),这使得用想买你的解法,上限难以确定,所以我开了dp[10000]的数组,还未得到好的优化和解释;(2)对比两种写法:1)for(i=1;i<=6;i++) for(j=a[i];j<=N;j++) dp[j]=min(dp[j], dp[j-a[i]]+1);for(i=1;i<=6;i++) for(j=N-a[i];j>=0;j--) dp[j]=min(dp[j], dp[j+a[i]]+1); 2)for(i=1;i<=... 阅读全文
posted @ 2012-08-16 19:00 tim11 阅读(161) 评论(0) 推荐(0)
poj 1384 Piggy-Bank (完全背包)
摘要:http://poj.org/gotoproblem?pid=1384普通的完全背包问题,稍微注意: for(j=w[i];j<=f-e;j++)具体代码:View Code #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int Inf = (1<<29);int t, e, f, n;int p[550], w[550];int dp[10100];int main(){ int i, j, k; while(scanf(&q 阅读全文
posted @ 2012-08-16 18:22 tim11 阅读(190) 评论(0) 推荐(0)
hdu 3535 AreYouBusy(三种背包)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=3535(1)本题是三种背包的综合应用, 至少选一种、最多选一种、任意选;(2)边读入边处理,可以节省一定的空间,也是代码更加清晰(如 m 就不用开数组m[120]);(3)初始化细节: 1)for(j=0;j<=t;j++) dp[i][j]=-(1<<28); 2)for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j]; 3)for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j]; 写题时, 我用了for(j=0... 阅读全文
posted @ 2012-08-16 16:33 tim11 阅读(132) 评论(0) 推荐(0)
hdu 1712 ACboy needs your help(分组背包)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1712(1)本题为分组背包问题,是基本类型。dp的核心是:for(i=1;i<=n;i++) for(j=1;j<=m;j++) for(k=m;k>=j;k--) dp[i][k]=max(dp[i][k], dp[i-1][k-j]+a[i][j]), dp[i][k]=max(dp[i][k], dp[i-1][k]); //被我忽略的一行我在写这题时,少掉了最后一行,一直WA,本质上是要对dp[i][k]赋予初值dp[i-1][k]:f... 阅读全文
posted @ 2012-08-16 15:03 tim11 阅读(123) 评论(0) 推荐(0)
hdu 3033 I love sneakers!(分组背包)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=3033(1)本题为分组背包问题,输入时将数据存入到结构体中:struct node{ int p[120], v[120], tot;}brand[12];(2)每组至少要取一个,处理方式不叫特殊,自然也是本题的关键。首先要初始化:for(i=1;i<12;i++) for(j=0;j<=m;j++) dp[i][j]=-(1<<28);即除了 i=0 以外,均是非法数据(注意,i=0 的一组千万不能赋负无穷)。之后是核心的部分:for(i=1;i<=k;i++) for(j=. 阅读全文
posted @ 2012-08-16 14:23 tim11 阅读(156) 评论(0) 推荐(0)
hdu 2955 Robberies(01背包)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2955(1)概率的预处理(常识):rp[i]=1-rp[i],并将概率相乘。若将概率相加(定式思维),案例是可以全过的,就麻烦了。。(2)初始化dp数组:偷走0百万是安全的,这很关键(dp[0]=1),其他的都是危险的(dp[i]=0),因为背包必须装满;(3)用sum 记录最大可能出现的值,结果也是从sum开始验证,符合安全条件的输出。具体代码:View Code #include<stdio.h>#include<stdio.h>#include<algorithm>u 阅读全文
posted @ 2012-08-16 13:09 tim11 阅读(133) 评论(0) 推荐(0)
hdu 1203 I NEED A OFFER!(01背包)
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1203(1)用到概率的一点常识,预处理:b[i]=1-b[i];(2)注意n和m的个子含义,n为钱数, m为组数,不能错用(如初始化时将m当做n用。。)(3)此题为简单的01背包问题。具体代码:View Code #include<stdio.h>#include<stdio.h>#include<algorithm>using namespace std;int n, m;int a[11000];float b[11000], dp[11000];int main(){ 阅读全文
posted @ 2012-08-16 12:43 tim11 阅读(146) 评论(0) 推荐(0)
opj 1948 Triangular Pastures(dp)
摘要:http://poj.org/problem?id=1948(1)用dp[i][j] 表示三角形的边为 i, j 存在与否,本质是对枚举的优化(dp), 另外,上限可取sum/2;(2)将 double p=sum/2.0 写错成 double p=sum/2,后果很严重;(3)存在两种更新方式: 1)for(i=1;i<=n;i++) for(j=sum/2;j>=0;j--) for(k=sum/2;k>=0;k--) { if(j>=a[i]) dp[j][k]=dp[j][k]||dp[j-a[i]][... 阅读全文
posted @ 2012-08-16 12:12 tim11 阅读(177) 评论(0) 推荐(0)
opj1837 Balance(dp)
摘要:http://poj.org/problem?id=1837(1)用dp[i][j]表示挂了 i 个重物时 平衡度为 j 的数目;(2)核心部分:for(j=1;j<=m;j++) for(k=0;k<=15000;k++) if(dp[j-1][k]) for(i=1;i<=n;i++) dp[j][k+c[i]*g[j]]+=dp[j-1][k];其中, j 表示重物编号, k 是背包, i 为所挂位置。注意循环的顺序,先确定重物,再打开背包,最后逐个转移平衡度。(3)由于力矩的变化才是本题的关键,将中间位置设为平衡位... 阅读全文
posted @ 2012-08-16 11:54 tim11 阅读(142) 评论(0) 推荐(0)