题目: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挂饰——压缩的动态规划的更多相关文章

  1. [BZOJ4247]挂饰(DP)

    当最终挂饰集合确定了,一定是先挂挂钩多的在挂挂钩少的. 于是按挂钩从大到小排序,然后就是简单的01背包. #include<cstdio> #include<algorithm> ...

  2. BZOJ4247挂饰

    Description     JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上.     JOI君的挂饰有一些与众不同--其中的一些挂饰附有可以挂其他挂件的挂钩 ...

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

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

  4. BZOJ4247 : 挂饰

    首先将挂饰按照挂钩个数从大到小排序,然后DP 设f[i][j]处理完前i个挂饰,还有j个多余挂钩的最大喜悦值,则 f[0][1]=0 f[i][j]=max(f[i-1][max(j-a[i],0)+ ...

  5. [bzoj4247][挂饰] (动规+排序)

    Description JOI君有N个装在手机上的挂饰,编号为1...N. JOI君可以将其中的一些装在手机上. JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩.每个挂件要么直 ...

  6. bzoj4247: 挂饰(背包dp)

    4247: 挂饰 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1136  Solved: 454[Submit][Status][Discuss] ...

  7. bzoj4247: 挂饰(背包)

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

  8. BZOJ4247 挂饰(动态规划)

    相当于一个有负体积的背包.显然如果确定了选哪些,应该先把体积小的挂上去.于是按体积从小到大排序,就是一个裸的背包了. #include<iostream> #include<cstd ...

  9. bzoj4247挂饰——DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4247 就是01背包: 把挂钩数限制在n以内,因为不需要更多,而这会带来一些问题,就是有很多挂 ...

随机推荐

  1. OAF页面集成条形码或者二维码

    OAF页面集成条形码 OAF生成条形码 OAF页面集成二维码跟这个类似,生成二维码需要以下jar包,zxing-core.jar, zxing-javase.jar,可自行去maven下载. 代码如下 ...

  2. EBS标准的查看供应商地点

    VO数据源:oracle.apps.pos.supplier.server.SitesVO SELECT pvsa.address_style, hzl.language, pvsa.province ...

  3. Mac安装fish shell

    1.brew update 2.brew install fish 3.sudo vi /etc/shells 增加内容:/usr/local/bin/fish   ##增加fish到shell环境变 ...

  4. redis中的"HashMap"

    redis是一个存储键值对的内存数据库,其存储键值的方式和java中的HashMap相似. 表征redis数据库的结构体是redisDb (在server.h文件中),redis服务器默认有16个数据 ...

  5. IIS6.0发布后对路径“D:\xxx\xxxx\web.config”的访问被拒绝问题的解决方法

    原来我本机发布后还是可以直接通过浏览器访问,这几天不知道怎么就不行,终于在网上找到解决方法 IIS发布后访问xxx/xxx/web.config路径被拒绝的问题截图如下: 解决方法: 1.在本地或服务 ...

  6. sql server中的go

    1. 作用:向 SQL Server 实用工具发出一批 Transact-SQL 语句结束的信号.2. 语法:一批 Transact-SQL 语句GO如Select 1Select 2Select 3 ...

  7. (C/C++学习笔记) 十七. 面向对象程序设计

    十七. 面向对象程序设计 ● 面向对象程序设计的基本概念 ※ 类实际上是一种复杂的数据类型,它不仅包含不同类型的数据,还包含对这些数据的一些必要的操作. 而对象则是这种复杂的数据类型的一个变量. 类是 ...

  8. linux定时任务:crontab命令

    crontab命令被用来提交和管理用户的需要周期性执行的任务,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查 ...

  9. “开始菜单”按钮今年8月将重回Windows 8

    本月早些时候微软明确表示,“开始菜单”将重新回归Windows 8操作系统.尽管微软当时并没有公布具体的时间表,但据熟悉微软内部运作的消息灵通人士透露称,“开始菜单”极有可能将出现在预计于今年8月发布 ...

  10. 逆向路由器固件之SQL注入 Part3

    另寻他径 在前面的内容中,我们使用TEW-654TR路由器的tftp服务实现了获取目标的管理权限.但是要是tftp没有开放到外网怎么办?另寻他径:在这一篇中会我们来分析一个web应用上的漏洞. 初步分 ...