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] ...
随机推荐
- socket in android
Server - JAVA package com.jim.ndkdemo; import android.net.LocalServerSocket; import android.net.Lo ...
- log4j日志系统
在项目开发中,记录错误日志是一个很有必要功能.一是方便调试:二是便于发现系统运行过程中的错误:三是存储业务数据,便于后期分析: 在java中,记录日志,有很多种方式. 比如,自己实现. 自己写类,将日 ...
- Subsets 集合子集 回溯
Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be ...
- 解决/home磁盘空间不足问题
最近在Linux下做仿真实验,但是渐渐的发现,/home原来分配的空间不足.通过先建硬盘分区,然后挂载到/home文件的方法,在网上查了好多资料 建立分区并挂载分区http://www.se126.c ...
- jsp内建对象的作用域
- 2019-6-23-开源项目使用-appveyor-自动构建
title author date CreateTime categories 开源项目使用 appveyor 自动构建 lindexi 2019-06-23 11:47:40 +0800 2019- ...
- 在window.onload中使用setTimeout
window.onload = function(){ function n(i){ alert(1); } setTimeout('n(1)',2000); } 以上代码会报错:n() is not ...
- AspNetPager 样式
使用方法: 1.引入样式表. 将 想要使用的样式表加入到本页面<style type="text/css"></style>标记中,或者新建一个css文件如 ...
- Android ListView批量选择(全选、反选、全不选)
APP的开发中,会常遇到这样的需求:批量取消(删除)List中的数据.这就要求ListVIew支持批量选择.全选.单选等等功能,做一个比较强大的ListView批量选择功能是很有必要的,那如何做呢? ...
- saltStack_Pillar
Pillar是Salt非常重要的一个组件,它用于给特定的minion定义任何你需要的数据,这些数据可以被Salt的其他组件使用.这里可以看出Pillar的一个特点,Pillar数据是与特定minion ...