JOISC2014 挂饰("01"背包)
传送门:
[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"背包)的更多相关文章
- BZOJ 4247 挂饰 01背包
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4247 JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机 ...
- P4138 [JOISC2014]挂饰
P4138 [JOISC2014]挂饰 ◦ N个装在手机上的挂饰.挂饰附有可以挂其他挂件的挂钩.每个挂件要么直接挂在手机上,要么挂在其他挂件的挂钩上.直接挂在手机上的挂件最多有1个. ...
- [JOISC2014]挂饰
嘟嘟嘟 这题其实还是比较好想的,就是有一个小坑点. 首先钩子多的排在前面,然后就是dp了. dp方程就是\(dp[i][j]\)表示到了第\(i\)建物品,还剩\(j\)个挂钩的最大喜悦值.转移就很显 ...
- 洛谷P4138 挂饰 背包
正解:背包dp 解题报告: 昂先放链接qwq 感觉还挺妙的,,,真的我觉得我直接做可能是想不到背包的,,,我大概想不出是个背包的QAQ 但是知道是背包之后觉得,哦,好像长得也确实挺背包的吼,而且其实是 ...
- 【BZOJ4247】挂饰 背包
[BZOJ4247]挂饰 Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他 ...
- 【bzoj4247】挂饰 背包dp
题目描述 JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩.每个挂件要么直接挂在手机上, ...
- bzoj4247: 挂饰(背包)
4247: 挂饰 题目:传送门 题解: 看完题目很明显的一道二维背包(一开始还推错了) 设f[i][j]表示前i个挂饰选完(可以有不选)之后还剩下j个挂钩的最大值(j最多贡献为n) 那么f[i][j] ...
- BZOJ 4247 挂饰 背包DP
4247: 挂饰 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id ...
- bzoj4247: 挂饰(背包dp)
4247: 挂饰 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1136 Solved: 454[Submit][Status][Discuss] ...
随机推荐
- PyCharm 头文件设置及作用
PyCharm 头文件 设置 进入File --->settings---->Editor---->File and Code Templates----->Python Sc ...
- (译)Objective-C的动态特性
这是一篇译文,原文在此,上一篇文章就是受这篇文章启发,这次干脆都翻译过来. 过去的几年中涌现了大量的Objective-C开发者.有些是从动态语言转过来的,比如Ruby或Python,有些是从强类型 ...
- Laravel 登录后清空COOKIE 方法
需求 在Laravel 登陆立即清空保存的COOKIE数组 实现 # Http/Controllers/Auth/LoginController.php public function redirec ...
- nodeJs学习-15 mysql中间件下载与使用、基本用法
下载mysql中间件(客户端):cnpm install mysql 链接数据库.查询示例: const mysql=require('mysql'); //1.连接 //createConnecti ...
- 2019.9.10附加题while练习
题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40万之 ...
- Nuxt.js打造旅游网站第1篇_项目环境搭建
1. 安装 使用官网提供的脚手架工具 create-nuxt-app,创建一个nuxtjs项目. npx create-nuxt-app xianyun 注意:在NPM版本5.2.0默认安装了npx, ...
- 【Linux】根目录命名的意义
1./bin :获得最小的系统可操作性所需要的命令2./boot :内核和加载内核所需的文件3./dev :终端.磁盘.调制解调器等的设备项4./etc :关键的启动文件和配置文件5./home :用 ...
- AutoCAD安装失败怎样卸载重新安装AutoCAD,解决AutoCAD安装失败的方法总结
技术帖:AutoCAD没有按照正确方式卸载,导致AutoCAD安装失败.楼主也查过网上关于如何解决AutoCAD安装失败的一些文章,是说删除几个AutoCAD文件和AutoCAD软件注册表就可以解决A ...
- 基于GIS的空间分析功能分析芝加哥小熊队和白袜队的球迷范围
将交换格式的文件转换为要素类 在ArcCatalog中新建地址定位器 设置地址定位器的样式 选择Arctoolbox->地理编码工具->对地址进行地理编码 定义坐标系 定义坐标系后如图所示 ...
- Javascript 用来验证电话号码的正则
Javascript 用来验证电话号码的正则 在学习 Javascript 时学习到的. function telephoneCheck(str) { // return /^(1\s?)?(\d{3 ...


