Description

JOI君有N个装在手机上的挂饰,编号为1...N。 JOI君可以将其中的一些装在手机上。
JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩。每个挂件要么直接挂在手机上,要么挂在其他挂件的挂钩上。直接挂在手机上的挂件最多有1个。
此外,每个挂件有一个安装时会获得的喜悦值,用一个整数来表示。如果JOI君很讨厌某个挂饰,那么这个挂饰的喜悦值就是一个负数。
JOI君想要最大化所有挂饰的喜悦值之和。注意不必要将所有的挂钩都挂上挂饰,而且一个都不挂也是可以的。

Input

第一行一个整数N,代表挂饰的个数。
接下来N行,第i行(1<=i<=N)有两个空格分隔的整数Ai和Bi,表示挂饰i有Ai个挂钩,安装后会获得Bi的喜悦值。 

Output

输出一行一个整数,表示手机上连接的挂饰总和的最大值

Sample Input

5
0 4
2 -2
1 -1
0 1
0 3

Sample Output

5

HINT

将挂饰2直接挂在手机上,然后将挂饰1和挂饰5分别挂在挂饰2的两个挂钩上,可以获得最大喜悦值4-2+3=5。
1<=N<=2000
0<=Ai<=N(1<=i<=N)
-10^6<=Bi<=10^6(1<=i<=N)

题解:我表示这道题是在老师和同学耗尽心思的讲解中才勉强懂了一点却因为输入输出调了十遍RE。。。

不过很开心的是这道题在他人的讲解和我看题解的过程中让我对动归的理解比以前稍微好了一点(虽然还是很菜),希望能有更多提升。

好啦看题目,这道题其实就是背包的容量在不停的变化,用f[i][j]来表示挂完第i个物品后还剩j个挂钩,那么转移方程为f[i][j]=max(f[i-1][j],f[i-1][max(j-a[i],0)+1]+b[i]);

为什么这么写呢?解释一下:首先f[i][j]=f[i-1][j]很好懂就是指现在这个物品不挂,可取得的喜悦值,那么f[i-1][max(j-a[i],0)+1]是什么意思呢,我们先看j-a[i]+1,这是指上一次的挂钩值,那么后面的这个式子意思是把这个饰件挂上的喜悦值+上一次的喜悦值,但是j-a[i]是有可能小于0的,即如果第i个物品挂上去的话这次不可能就j个挂钩,这个时候我们就假设上一次只剩了一个挂钩,这样j个挂钩都是现在第i个物品带来的,即使j-a[i]<0,也可以当做我们把多余j的挂钩给舍去了。为什么我们要假设上一次只剩了一个挂钩呢?因为当前物品如果能挂上去,说明上一次多出的挂钩数一定大于等于1,却不能保证大于1,所以我们至多只能设上次只剩了一个挂钩(只有一是能被确定的),这就是这个式子让我当时最不理解的地方。。。。。

好啦,第二个重点,在做动归前我们需要将a数组排一下序,为何因为我们会发现如果不排序的话我们这次挂上这个饰品,即使j是负数也并不是不合法的,因为挂饰间可以互换位置,只要后面挂饰的挂钩能够把j在最后补成自然数就可以了,那样就会导致动归的循环不确定,没法一步步推,所以要进行排序。

ps:最好别用输入输出流,我的RE好像就错在这,可能是因为输入数据有点大吧。。。

具体程序:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct h{
int k,t;
}x[];
int cmp(const h&a,const h&b)
{
return a.k>b.k;
}
int max(int a,int b)
{
return (a>b?a:b);
}
int f[][];
int pop,n,ans;
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d %d",&x[i].k,&x[i].t) ;
//k为挂钩数,t为喜悦值
sort(x+,x+n+,cmp);//排序
memset(f,-,sizeof(f));//先预处理为最小值
f[][]=;//手机上原来就有个挂钩所以算作0;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
f[i][j]=max(f[i-][j],f[i-][max(j-x[i].k,)+]+x[i].t);
ans=;
for (int i=;i<=n;i++)
ans=max(ans,f[n][i]);//去看看最后的答案
printf("%d",ans);
return ;
}

BZOJ 4247: 挂饰 题解的更多相关文章

  1. BZOJ 4247 挂饰 背包DP

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

  2. BZOJ 4247 挂饰(背包问题)

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

  3. BZOJ 4247 挂饰 01背包

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

  4. bzoj 4247: 挂饰【dp】

    bzoj上访问负下标会跑到奇怪的地方-- 其实可以滚动数组优化,但是我看能过就懒得改了 设f[i][j]为已经算了前i个挂饰,当前有j个空的钩子,转移就是f[i][j]=max(f[i-1][j],f ...

  5. BZOJ 4247: 挂饰

    背包裸题 #include<cstdio> #include<algorithm> using namespace std; int F[2005]; struct node{ ...

  6. BZOJ 4247: 挂饰 动态规划

    按照挂件数量排序,然后做一个 DP 就好了. code: #include <bits/stdc++.h> #define ll long long #define N 2003 #def ...

  7. bzoj 4247挂饰

    背包????不会... #include<bits/stdc++.h> #define INF 0x7fffffff #define LL long long #define N 1000 ...

  8. bzoj千题计划197:bzoj4247: 挂饰

    http://www.lydsy.com/JudgeOnline/problem.php?id=4247 先把挂饰按挂钩数量从大到小排序 dp[i][j]前i个挂饰,剩下j个挂钩的最大喜悦值 分挂和不 ...

  9. bzoj4247: 挂饰(背包)

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

随机推荐

  1. python的中文编码问题

    下文转自 http://blog.csdn.net/mayflowers/article/details/1568852 1.        在Python中使用中文 在Python中有两种默认的字符 ...

  2. CRM 权限与分派不一样问题

    问题描述: 1 userA用户 为 区域经理; 2  区域经理(角色) 为 分派给userA的安全角色; 3  区域经理(角色) 设置了对实体 客户 的读权限为 业务部门级; 按正常来说userA 应 ...

  3. iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

    http://blog.csdn.net/totogo2010/article/details/8016129 GCD很好的博文

  4. System.TypeInitializationException: The type initializer for 'Mono.Unix.Native.Stdlib' threw an exception.

    08-31 17:02:03: ### DEBUG ##########################System.TypeInitializationException: The type ini ...

  5. 39. Recover Binary Search Tree && Validate Binary Search Tree

    Recover Binary Search Tree OJ: https://oj.leetcode.com/problems/recover-binary-search-tree/ Two elem ...

  6. 如何定义DATATABLE,同时赋值

    //定义一个Table DataTable dt=new DataTable("yeji"); DataRow dr; DataColumn dc; //添加第0列 dc=new ...

  7. mysql 不是主键不能删除的保护问题解决办法?

       select * from t_answerexams;      delete from  t_answerexams  where  selectid = 'c4582502-8b27-44 ...

  8. 修改Django的默认打印时间

    环境 Django版本:1.10 前言 默认情况下,Django会把日期按照“月份 天数, 年”的格式打印,比如2003年2月4日会打印成“Feb. 4, 2003”,这种格式对于西方人来说很好看,但 ...

  9. Border-radius属性--设置圆角边框

    border-radius:该属性允许您为元素添加圆角边框! div { border:2px solid; border-radius:25px; -moz-border-radius:25px; ...

  10. 基于PHP生成静态页的实现方法

    t1.php 复制代码 代码如下: <?php// 方法一根据模版生成静态页面// replaceTemplateString函数用于替换模板中指定字符串function replaceTemp ...