bzoj4247挂饰——压缩的动态规划
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4247
1.dp之前要先按挂钩个数从大到小排序,不然挂钩一度用成负的也可能是正确的,不仅脚标难存,而且不知道各种时刻负多少以内是合法的。
2.但是最多有4000000个挂钩,省掉一维勉强开下数组也就罢了,会TLE!
考虑多余n=2000个的挂钩就不会被用上了,所以第二维开成2000;
(——状态表示至少有 j 个挂钩!!!)
那么当a [ i ] > j 的时候怎么办呢?大家都是这么写的:
d [ i ] [ j ] = max( d [ i -1 ] [ j ] , d [ i - 1 ] [ max( j - a [ i ] , 0) +1 ] + b [ i ] );
也就是若a [ i ] > j,则d [ i ] [ j ] = max( d [ i -1 ] [ j ] , d [ i - 1 ] [ 1 ] + b [ i ] ),然后把多出来的挂钩忽略;
为什么一定是1而不是k(1<=k<=j)呢?因为d [ ] [ 1 ]一定是最大的值!
这是因为d [ ] [ 1 ]其实可能有很多挂钩,但把多余挂钩都忽略了,所以记录的其实是所有剩余挂钩中的最大值;
那么0也是啊?
但0的话不能再挂东西了,而只要剩下1个挂钩,就可以往上挂下一个东西,所以1可以一直被更新;
如果剩下的东西都是0挂钩怎么办?
所以才不能只记录d [ ] [ 1 ],而要记录到n,这样该挂饰实际有多个挂钩的优势也不会被忽略了!
3.所以到最后1表示有剩余挂钩的最大值,0表示无剩余挂钩的最大值;
但其实每次都会用1的值更新0的值,所以最后直接输出0的值就行了!也就是像状态定义的一样,0包含了所有情况。
4.突然想到,那么即使当 j - a [ i ] > 0,也不一定用 d [ i -1 ] [ j - a [ i ] ]来更新,只需用 k ( j - a [ i ] <= k <= j )然后忽略多余挂钩就行了;
那为什么不这样呢?因为 j 的值越大,相当于对挂钩数的限制越严,卡掉的状态也越多,值就越来越不优了!
所以尽量用靠前的 j 值来更新!
5.所以应该是n^2的复杂度才对,为什么是约6000ms?而且那种省掉一维的写法为什么不行?
updt(2018.9.18):当j==0时max(j-r[i].a,0)+1==1,会用到本层的值,应该用上一层的值。
折中的方法是滚动数组。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
long long d[],ans;
struct Node{
int a,c;
}r[];
bool cmp(Node x,Node y){return x.a>y.a;}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&r[i].a,&r[i].c);
sort(r+,r+n+,cmp);
memset(d,-,sizeof d);
d[]=;
for(int i=;i<=n;i++)
{
// printf("i=%d a[i]=%d c[i]=%d\n",i,r[i].a,r[i].c);
// lm+=r[i].a;
if(!r[i].a)//
for(int j=;j<=n;j++)
d[j]=max(d[j],d[j+]+r[i].c);
else for(int j=n;j>=;j--)
d[j]=max(d[j],d[max(j-r[i].a,)+]+r[i].c);
}
ans=-2e9-;
for(int i=;i<=n;i++)//i=0
ans=max(ans,d[i]);
printf("%lld",ans);
return ;
}
省掉一维的WA
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
long long d[][],ans;
struct Node{
int a,c;
}r[];
bool cmp(Node x,Node y){return x.a>y.a;}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&r[i].a,&r[i].c);
sort(r+,r+n+,cmp);
memset(d,-,sizeof d);
d[][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
d[i][j]=max(d[i-][j],d[i-][max(j-r[i].a,)+]+r[i].c);
}
// ans=-2e9-7;
// for(int i=0;i<=n;i++)//i=0
// ans=max(ans,d[n][i]);
// ans=max(d[n][0],d[n][1]);
printf("%lld",d[n][]);
return ;
}
bzoj4247挂饰——压缩的动态规划的更多相关文章
- [BZOJ4247]挂饰(DP)
当最终挂饰集合确定了,一定是先挂挂钩多的在挂挂钩少的. 于是按挂钩从大到小排序,然后就是简单的01背包. #include<cstdio> #include<algorithm> ...
- BZOJ4247挂饰
Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同--其中的一些挂饰附有可以挂其他挂件的挂钩 ...
- bzoj千题计划197:bzoj4247: 挂饰
http://www.lydsy.com/JudgeOnline/problem.php?id=4247 先把挂饰按挂钩数量从大到小排序 dp[i][j]前i个挂饰,剩下j个挂钩的最大喜悦值 分挂和不 ...
- BZOJ4247 : 挂饰
首先将挂饰按照挂钩个数从大到小排序,然后DP 设f[i][j]处理完前i个挂饰,还有j个多余挂钩的最大喜悦值,则 f[0][1]=0 f[i][j]=max(f[i-1][max(j-a[i],0)+ ...
- [bzoj4247][挂饰] (动规+排序)
Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩.每个挂件要么直 ...
- bzoj4247: 挂饰(背包dp)
4247: 挂饰 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1136 Solved: 454[Submit][Status][Discuss] ...
- bzoj4247: 挂饰(背包)
4247: 挂饰 题目:传送门 题解: 看完题目很明显的一道二维背包(一开始还推错了) 设f[i][j]表示前i个挂饰选完(可以有不选)之后还剩下j个挂钩的最大值(j最多贡献为n) 那么f[i][j] ...
- BZOJ4247 挂饰(动态规划)
相当于一个有负体积的背包.显然如果确定了选哪些,应该先把体积小的挂上去.于是按体积从小到大排序,就是一个裸的背包了. #include<iostream> #include<cstd ...
- bzoj4247挂饰——DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4247 就是01背包: 把挂钩数限制在n以内,因为不需要更多,而这会带来一些问题,就是有很多挂 ...
随机推荐
- Linux文件与目录管理(一)
一.Linux文件与目录管理 1.Linux的目录结构是树状结构,最顶级的目录是根目录/(用"/"表示) 2.Linux目录结构图: /bin:bin是Binary的缩写,这个目录 ...
- consumer发送请求,接收响应
一般情况,consumer发送请求时,创建一个DefaultFuture对象,然后阻塞并等待响应.DefaultFuture类,封装了请求和响应: // 省略其他代码 public class Def ...
- 071——VUE中vuex之使用getters计算每一件购物车中商品的总价
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP:第三章——数组中的array_values
例: <?php header("Content-Type:text/html;charset=utf-8"); //array_value(); //功能:返回数组中所有的 ...
- C# 值类型与引用类型 (上)
1. 主要内容 类型的基本概念 值类型深入 引用类型深入 值类型与引用类型的比较及应用 2. 基本概念 C#中,变量是值还是引用仅取决于其数据类型. C#的基本数据类型都以平台无关的方式来定义,C#的 ...
- Superset 制作图表
参考资料: http://lxw1234.com/archives/2018/03/904.htm https://wenku.baidu.com/view/49ffdf8b77eeaeaad1f34 ...
- hdu 1003 Max Sum (动态规划)
转载于acm之家http://www.acmerblog.com/hdu-1003-Max-Sum-1258.html Max Sum Time Limit: 2000/1000 MS (Java/O ...
- 第三视角团队:项目UML设计(团队)
项目UML设计(团队) 团队信息 团队名:第三视角 各成员学号及姓名 姓名 学号 博客链接 张扬(组长) 031602345 http://www.cnblogs.com/sxZhangYang/p/ ...
- 指针和const一些注意事项
1.常量指针(底层const) 指向常量的指针,指针所指向的对象的值无法被修改,若想存放常量对象的地址,只能使用指向常量的指针. 2.指针常量(顶层const) 指针本身是常量,指针本身的值不可修改. ...
- android开源项目集合
ZXing http://code.google.com/p/zxing/ 条形码.二维码 K-9 Mail http://code.google.com/p/k9mail/ 邮件客户端 Sipdro ...