~~~题面~~~

题解:

  感到此题非常的神奇。。。看了大佬的题解才懂的。

  首先建模:

  先把所有队伍的出去回来时间都放在一个数组里,然后排序,从左到右扫一边,给每个队伍都建一个带权点,进行如下操作:

  (s表示出发,t表示回家, len表示两个点之间的时间差)  

  1,对于s --- > t的情况,如果两者属于一个队伍,那么给这个队伍加上len,表示如果给这个队伍钥匙可以获得的贡献。

    如果两者不属于同一个队伍,那么在这两个队伍之间连一条边权为len的边,表示如果同时给这2个队伍钥匙可以获得的贡献。

  2,对于s ---> s的情况,给左边的队伍加上len,表示如果给左边队伍钥匙可以获得的贡献。

  3,对于t ---> t的情况,给右边队伍加上len,表示如果给右边队伍钥匙可以获得的贡献。

  4,对于t ---> s的情况,直接给ans += len,因为不需要钥匙就可以获得这个贡献。

  然后考虑如何DP。

  我们观察到每个点最多只有一条入边,最多只有一条出边,因此这些点和边构成了由一堆链组成的图。而这些链两两不相交(不互相干扰)

  因此我们只需要保证在DP时,一条链中的点都按顺序放在一起即可。所以我们对整张图做一个拓扑排序,最后得到的DP顺序应该是类似这样的:(可能有点单独成链)

  相当于把所有链一一放好,然后DP。

  那么如何转移呢?

  设f[i][j][0/1]表示DP到i位,当前选了j个点,当前点选or不选的贡献。

  那么对于不相连的点,直接更新即可,

  对于相连的点,如果用f[i - 1][j - 1][1]更新f[i][j][1],那么还需要加上两点之间边的边权,表示两个点同时选带来的多余贡献。

  最后的答案等于ans = d[n * 2] - d[1] - ans - max(f[i][j][1], f[i][j][0]);

  d[n * 2] - d[1]是在获取整个线段的长度,减去ans是在减掉一开始就有的贡献(无需钥匙的),max(f[i][j][0], f[i][j][1])是给钥匙带来的贡献,相减后剩下的就是开门的天数。

  (一遍A,感到非常愉悦,而且速度还可以)

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 2100
#define ac 5000
#define LL long long int n, k, cnt, ans;
int power[AC], Next[AC], last[AC];
int in[AC], d[AC], tot;//存下DP序列
LL s[AC], f[AC][AC][];
bool z[AC];
//DP到i位,选了j个点,当前点选与不选,s是当前点的向后的边的边权
struct node{
int x, id;
bool z;
}p[ac]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline bool cmp(node a, node b)
{
return a.x < b.x;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} void dfs(int x)
{
d[++tot] = x, z[x] = true;
while(Next[x]) d[++tot] = Next[x], x = Next[x], z[x] = true;
} void pre()
{
n = read(), k = read();
for(R i = ; i <= n; i ++)
{
p[++cnt] = (node){read(), i, };
p[++cnt] = (node){read(), i, };
}
sort(p + , p + cnt + , cmp);
int b = * n;
for(R i = ; i < b; i ++)
{
int len = p[i + ].x - p[i].x, x = p[i].id, y = p[i + ].id;
if(!p[i].z && p[i + ].z)
{
if(x == y) power[p[i].id] += len;
else Next[x] = y, last[y] = x, s[x] = len, ++ in[y];
}
else if(!p[i].z && !p[i + ].z) power[x] += len;
else if(p[i].z && p[i + ].z) power[y] += len;
else ans += len;
}
} void work()
{
int b = * n;
for(R i = ; i < b; i ++) //类似于拓扑排序,要没有入度才行
if(!z[p[i].id] && !in[p[i].id]) dfs(p[i].id);
for(R i = ; i <= n; i ++)//枚举点
{
for(R j = ; j <= k; j ++)
{
f[i][j][] = max(f[i - ][j][], f[i - ][j][]);
if(last[d[i]]) f[i][j][] = max(f[i - ][j - ][], f[i - ][j - ][] + s[last[d[i]]]) + power[d[i]];
else f[i][j][] = max(f[i - ][j - ][], f[i - ][j - ][]) + power[d[i]];
}
}
printf("%lld\n", p[n * ].x - ans - p[].x - max(f[n][k][], f[n][k][]));
} int main()
{
freopen("in.in", "r", stdin);
pre();
work();
fclose(stdin);
return ;
}

[LG4890]Never·island DP的更多相关文章

  1. cf.301.D. Bad Luck Island(dp + probabilities)

    D. Bad Luck Island time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. CodeForces 540D Bad Luck Island (DP)

    题意:一个岛上有石头,剪刀和布,规则就不用说了,问你最后只剩下每一种的概率是多少. 析:很明显的一个概率DP,用d[i][j][k]表示,石头剩下 i 个,剪刀剩下 j 个,布剩下 k 个,d[r][ ...

  3. HDU-3502-Huson&#39;s Adventure Island(BFS+如压力DP)

    Problem Description A few days ago, Tom was tired of all the PC-games, so he went back to some old F ...

  4. bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp

    1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1826  Solved: 405[Submit][S ...

  5. P4890 Never·island(dp)

    P4890 Never·island 求门开的最小时间,其实也就是求门关的最大时间. 坐标这么大....显然坐标要离散化 离散化排序后,我们发现x轴被这些点划分成若干条线段$(l,r)$,并且有4种情 ...

  6. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

  7. Codeforces Round #301 (Div. 2) D. Bad Luck Island 概率DP

    D. Bad Luck Island Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/540/pr ...

  8. CF#301 D:Bad Luck Island (概率dp)

    D:Bad Luck Island 一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j] ...

  9. CF 540D——Bad Luck Island——————【概率dp】

    Bad Luck Island time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

随机推荐

  1. web开发学习路线

    第一阶段: HTML+CSS: HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础: Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMA ...

  2. tp5多条件查询

    ->where('m.user_nickname|w.nickname|c.companyname','like','%'.$search.'%')\

  3. AB PLC 编程之状态机

    AB的程序设计和西门子有点PLC不大一样,在AB中没有RS指令,所以主要用move指令来作步进.今天我们就用Move指令写个AB的程序,和西门子比,有哪些不同. 控制任务 很简单的一个状态机.初始步为 ...

  4. 安装java 和 eclipse

    昨天安装eclipse出现个问题, 安装完了创建第一个项目目录的时候弹窗报错an ......什么什么, 百度一堆没有用,后来发现是jdk12不支持,换了jdk8就可以了, 然后eclipse安装py ...

  5. 算法竞赛入门经典-1.5.4 Q&A

    这小节考察实践能力,要求在不要查书.不要网上找答案,自己用实验的方法解决以下五个问题: 做这五道题时,好几道都没思路,违反了规则到网上找了一圈,居然没找到答案,于是打算写这篇博客.不知是否有更好的实践 ...

  6. mybatis 打印SQL

    如果使用的是application.properties文件,加入如下配置: #打印SQL logging.level.com.jn.ssr.supererscuereporting.dao=debu ...

  7. Java线程和多线程(九)——死锁

    Java中的死锁指的就是一种多于两个线程永远阻塞的特殊状况.Java中的死锁状态至少需要多于两个线程以及资源的时候才会产生.这里,我写了一个产生死锁的程序,并且讲下如何分析死锁. 首先来看一下产生死锁 ...

  8. 虚拟现实-VR-UE4-创建C++版工程

    首先,创建C++版本的UE4 项目工程,我使用的是4.12.3版本,据了解,新版本后面的编译都是vs2015 所以,想要创建C++版本的工程,就需要安装vs2015 至于vs2015的安装,自己百度吧 ...

  9. 为什么logstash进程的CPU使用率100%?

    机器上有个进程cpu使用率很高,近100%了, Tasks: 120 total, 2 running, 118 sleeping, 0 stopped, 0 zombie%Cpu(s): 99.0 ...

  10. 为什么mysqld启动报错

    在一台ubuntu测试机器上启动一个mysql实例,本来应该是一件很简单的事情, 启动的时候却报错了:   mysqld_safe --defaults-file=/etc/mysql/my3307. ...