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. 【转】C# 使用消息队列,包括远程访问

    出处:http://www.cnblogs.com/80X86/p/5557801.html 近期做一个小的功能需求,用到了队列,用的时候出了很多问题,现在总结一下,希望能对有需要的人提供帮助. 我的 ...

  2. Haproxy+asp.net +RedisSessionStateProvider 完美实现负载均衡,并且session保持

    .net framework 4.5下测试成功,使用RedisSessionStateProvider 2.2.1保持session数据,通过Haproxy保持会话数据.首先在PM下安装RedisSe ...

  3. Angular学习

    一.Angular是什么 基于JS的框架,类似JQuery,利用数据绑定和依赖注入实现页面数据的渲染,无需人为写大量的JS,减少了代码量,优美了代码. 二.Angular优缺点 Angular适用与C ...

  4. dom4j生成xml

    package com.yunfengtech.solution.business; import java.io.FileOutputStream; import org.dom4j.Documen ...

  5. 49. Search in Rotated Sorted Array && Search in Rotated Sorted Array II

    Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you before ...

  6. Linux学习笔记(一)

    1.正则表达式 \w 匹配任何字类字符,包括下划线.与“[A-Za-z0-9_]”等效. \W 与任何非单词字符匹配.与“[^A-Za-z0-9_]”等效. +    一次或多次匹配前面的字符或子表达 ...

  7. C++设计模式-Builder建造者模式

    作用:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:B ...

  8. java 单例设计模式

    1.饿汉单例设计模式:  步骤 :   1.定义一个私有的静态成员变量来引用对象(私有的静态对象),设置对象唯一.   2.私有化构造方法,防止new对象.   3.创建一个公开的静态方法,返回上面的 ...

  9. Android 实现多行文本跑马灯效果

    Android TextView 实现跑马灯的效果很简单,只要加三个属性就可以了. android:ellipsize="marquee" android:focusable=&q ...

  10. QlikView TEXT控件固定显示图片

    QlikView 的Text控件不仅可以用来展示文本也可以用来展示图片. 数据表 2个列,一个是 关联字段(Country),另外一个保存图片物理路径. TEXT控件固定显示图片 ,编辑控件表达式 = ...