[LG4890]Never·island DP
题解:
感到此题非常的神奇。。。看了大佬的题解才懂的。
首先建模:
先把所有队伍的出去回来时间都放在一个数组里,然后排序,从左到右扫一边,给每个队伍都建一个带权点,进行如下操作:
(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的更多相关文章
- 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 ...
- CodeForces 540D Bad Luck Island (DP)
题意:一个岛上有石头,剪刀和布,规则就不用说了,问你最后只剩下每一种的概率是多少. 析:很明显的一个概率DP,用d[i][j][k]表示,石头剩下 i 个,剪刀剩下 j 个,布剩下 k 个,d[r][ ...
- HDU-3502-Huson'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 ...
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- P4890 Never·island(dp)
P4890 Never·island 求门开的最小时间,其实也就是求门关的最大时间. 坐标这么大....显然坐标要离散化 离散化排序后,我们发现x轴被这些点划分成若干条线段$(l,r)$,并且有4种情 ...
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
- 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 ...
- CF#301 D:Bad Luck Island (概率dp)
D:Bad Luck Island 一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j] ...
- CF 540D——Bad Luck Island——————【概率dp】
Bad Luck Island time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
随机推荐
- Node.js 学习笔记 (一) 安装配置
Node.js 安装配置 本安装教程以Node.js v4.4.3 LTS(长期支持版本)版本为例 Window 上安装Node.js 你可以采用以下两种方式来安装. 1.Windows 安装包(.m ...
- Str_turn
public class Str_turn { public static void main(String args[]) { String Str1 = new String("This ...
- (数据科学学习手札19)R中基本统计分析技巧总结
在获取数据,并且完成数据的清洗之后,首要的事就是对整个数据集进行探索性的研究,这个过程中会利用到各种描述性统计量和推断性统计量来初探变量间和变量内部的基本关系,本篇笔者便基于R,对一些常用的数据探索方 ...
- 【转】iOS库 .a与.framework区别
转自:http://blog.csdn.net/lvxiangan/article/details/43115131 一.什么是库? 库是共享程序代码的方式,一般分为静态库和动态库. 二.静态库与动态 ...
- 实用脚本 1 -- 安装Ctags
Ctags是vim下方便代码阅读的工具,一般VIM中已经默认安装了Ctags,它可以帮助程序员很容易地浏览源代码. 1.如果系统中没有此工具用如下方法安装: 到ctags官网下载源码,解压后 ...
- 【PHP】进一法取整、四舍五入取整、忽略小数等的取整数方法大全
PHP取整数函数常用的四种方法,下面收集了四个函数:经常用到取整的函数,今天小小的总结一下!其实很简单,就是几个函数而已--主要是:ceil,floor,round,intval PHP取整数函数常用 ...
- 思杰VDI提示“The VDI is not available”
前言:困扰已久的问题终于解决. 问题:客户反馈无法连接VDI. 解决过程:1.登录后台查看VDI状态为关机状态尝试重新启动提示如下图: 2.判断此VDI的启动盘出现问题(注:本人环境无数据盘) 3.查 ...
- 「日常训练」「小专题·图论」Domino Effect(1-5)
题意 分析 这题几乎就是一条dijkstra的问题.但是,如何考虑倒在中间? 要意识到这题求什么:单源最短路的最大值.那么有没有更大的?倒在中间有可能会使它更大. 但是要注意一个问题:不要把不存在的边 ...
- selenide UI自动化进阶二 pageObject实现页面管理
首先定义登录页面,上代码吧 LoginPage.java package com.test.selenium.page; import org.openqa.selenium.By; import s ...
- python 基础篇 06 编码 以及小知识点补充
本节主要内容: 1. is和==的区别2. 编码的问题 ⼀. is和==的区别1. id()通过id()我们可以查看到⼀个变量表⽰的值在内存中的地址 注 ----<<<在pytho ...