传送门:

  [1]:洛谷

  [2]:BZOJ

参考资料:

  [1]:追忆:往昔

题解

  上述参考资料的讲解清晰易懂,下面谈谈我的理解;

  关键语句:

  

  将此题转化为 "01背包" 类问题,关键就是上述语句;

  据此,定义 dp[ i ][ j ] 表示前 i 个物品在钩子剩余 j 个的状态下所获得的最大喜悦值;

  细节处理:

  

  为了应对负数的情况,让 dp[ i ][ j ] 的下标 j 全部增加 2000 ,这样就可以表示在负数范围内的值了。

  状态转移:

  首先,初始化 dp[][] 数组为 -INF,并令 dp[0][2001]=0(初始手机上含有一个挂钩);

 for(int i=;i <= n;++i)
{
a[i]--;
for(int j=;j <= ;++j)
{
dp[i][j]=max(dp[i][j],dp[i-][j]);
if(dp[i][j] == -INF)
continue; int k=min(j+a[i],);
dp[i][k]=max(dp[i][k],max(dp[i-][j]+b[i],dp[i-][k]));
}
}

  解释1:挂饰 i 可以提供 ai 个挂钩,但是,要把它挂到手机上需要消耗一个挂钩,所以,挂饰 i 额外提供 ai-1 个挂钩;

  解释2:第6行的更新是必不可少的,手动测试如下样例便可明白:


  解释3:第 11 行,dp[ i ][ k ] 只受状态 dp[ i-1 ][ j ] 和 dp[ i-1 ][ k ] 的影响,为什么在判断的时候需要额外与 dp[ i ][ k ] 判断呢?

       仔细看一下 k,如果 j+a[ i ] 超过上界 4000,那么 k = 4000,对于超过 4000 的肯定都更新到了 dp[ i ][ 4000 ]上;

       所以,dp[ i ][ 4000 ] 会首其他状态的影响,而不只是上述两种状态的影响;

  验证解释3的正确性:

  将第 11 行代码改成如下所示代码(AC):

 if(k < )
dp[i][k]=max(dp[i-][j]+b[i],dp[i-][k]);
else
dp[i][k]=max(dp[i][k],max(dp[i-][j]+b[i],dp[i-][k]));

  而改成如下所示代码(WA):

 dp[i][k]=max(dp[i-][j]+b[i],dp[i-][k]);

•Code

 #include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=2e3+; int n;
int a[maxn];
int b[maxn];
int dp[maxn][maxn<<]; int Solve()
{
for(int i=;i <= n;++i)
for(int j=;j <= ;++j)
dp[i][j]=-INF; dp[][]=;
for(int i=;i <= n;++i)
{
a[i]--;///物品i本身需要占用一个钩子,所以其可以提供的钩子个数为a[i]-1
for(int j=;j <= ;++j)
{
dp[i][j]=max(dp[i][j],dp[i-][j]); if(dp[i][j] == -INF)
continue; int k=min(j+a[i],);
dp[i][k]=max(dp[i][k],max(dp[i-][j]+b[i],dp[i-][k]));
}
}
int ans=;
for(int i=;i <= ;++i)
ans=max(ans,dp[n][i]);
return ans;
} int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
scanf("%d",&n);
for(int i=;i <= n;++i)
scanf("%d%d",a+i,b+i); printf("%d\n",Solve()); return ;
}

二维dp

•利用滚动数组降低dp的维数

  

•Code

 #include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=2e3+; int n;
int a[maxn],b[maxn];
int dp[maxn<<]; int Solve()
{
mem(dp,-INF);
dp[]=; for(int i=;i <= n;++i)
{
a[i]--;
if(a[i] > )
{
for(int j=;j >= ;--j)
{
if(dp[j] == -INF)
continue;
int k=min(j+a[i],);
dp[k]=max(dp[j]+b[i],dp[k]);
}
}
else
{
for(int j=;j <= ;++j)
{
if(dp[j] == -INF)
continue;
dp[j+a[i]]=max(dp[j]+b[i],dp[j+a[i]]);
}
}
}
int ans=;
for(int i=;i <= ;++i)
ans=max(ans,dp[i]); return ans;
}
int main()
{
scanf("%d",&n);
for(int i=;i <= n;++i)
scanf("%d%d",a+i,b+i); printf("%d\n",Solve()); return ;
}

一维dp(滚动数组)

JOISC2014 挂饰("01"背包)的更多相关文章

  1. BZOJ 4247 挂饰 01背包

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4247 JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机 ...

  2. P4138 [JOISC2014]挂饰

    P4138 [JOISC2014]挂饰 ◦          N个装在手机上的挂饰.挂饰附有可以挂其他挂件的挂钩.每个挂件要么直接挂在手机上,要么挂在其他挂件的挂钩上.直接挂在手机上的挂件最多有1个. ...

  3. [JOISC2014]挂饰

    嘟嘟嘟 这题其实还是比较好想的,就是有一个小坑点. 首先钩子多的排在前面,然后就是dp了. dp方程就是\(dp[i][j]\)表示到了第\(i\)建物品,还剩\(j\)个挂钩的最大喜悦值.转移就很显 ...

  4. 洛谷P4138 挂饰 背包

    正解:背包dp 解题报告: 昂先放链接qwq 感觉还挺妙的,,,真的我觉得我直接做可能是想不到背包的,,,我大概想不出是个背包的QAQ 但是知道是背包之后觉得,哦,好像长得也确实挺背包的吼,而且其实是 ...

  5. 【BZOJ4247】挂饰 背包

    [BZOJ4247]挂饰 Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他 ...

  6. 【bzoj4247】挂饰 背包dp

    题目描述 JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩.每个挂件要么直接挂在手机上, ...

  7. bzoj4247: 挂饰(背包)

    4247: 挂饰 题目:传送门 题解: 看完题目很明显的一道二维背包(一开始还推错了) 设f[i][j]表示前i个挂饰选完(可以有不选)之后还剩下j个挂钩的最大值(j最多贡献为n) 那么f[i][j] ...

  8. BZOJ 4247 挂饰 背包DP

    4247: 挂饰 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  9. bzoj4247: 挂饰(背包dp)

    4247: 挂饰 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1136  Solved: 454[Submit][Status][Discuss] ...

随机推荐

  1. 【JZOJ3854】【NOIP2014八校联考第2场第2试9.28】分组(group)

    MEi Bsny所在的精灵社区有n个居民,每个居民有一定的地位和年龄,ri表示第i个人的地位,ai表示第i个人的年龄. 最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长 ...

  2. iOS 开发该选择Blocks还是Delegates

    http://www.cocoachina.com/ios/20150925/13525.html 前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中 ...

  3. day39-Spring 01-上次课内容回顾

  4. [idea]Error:java: invalid source release: 1.8 标签: idea 2017-02-24 15:50 961人阅读

    最近用idea敲struts,虽然idea的界面很好看,代码提示也很强大,不过也的确是碰到了一些在eclipse上从来没有碰到过的问题,而且我发现,idea的错误,很多都是在外国的网站上提问的人比较多 ...

  5. More Effective C++: 05技术(29)

    29:引用计数 本章首先实现一个带引用计数String,然后逐步优化,介绍引用计数的常规实现. 实现引用计数的String,首先需要考虑:引用计数在哪存储.这个地方不能在String对象内部,因为需要 ...

  6. Git同步Python代码

    之前我们都是将代码保存到本地目录, 然后再上传到Git中,但如果针对在pycharm中的代码,就要换另一种方式了,下面简单介绍一下. 1.打开pycharm主界面,选择菜单栏VCS---checkou ...

  7. 三.使用JDBC处理MySql大数据

    一.基本概念 大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时 ...

  8. 2013年山东省第四届ACM大学生程序设计竞赛E题:Alice and Bob

    题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynom ...

  9. 容器化ICT融合初体验

    [编者的话]本次将分享的容器化ICT融合平台是一种面向未来ICT系统的新型云计算PaaS平台,它基于容器这一轻量级的虚拟化技术以及自动化的"微服务"管理架构,能够有效支撑应用快速上 ...

  10. wepy中组件之间通信方法

    events events是WePY组件事件处理函数对象,存放响应组件之间通过broadcast.emit.$invoke所传递的事件的函数. $broadcast —— 父往子传 $broadcas ...