一开始想的贪心,可是发现贪心的问题太多了啊!只能保证当前最优,全局完全无法考虑。

所以正解是dp。预处理出前缀和,枚举每个区间,在每个点记录$now[i]$表示以$i$这个塔结尾的塔组目前的高度。$dp[i]$表示以$i$这个塔结尾最多能分成多少组。如果$dp[i]$可以更新成更优值,则直接更新$dp$和$now$值,否则如果$dp$值相同,则尽量使$now$值最小。

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std; ll n, h[], pre[], now[], dp[]; int main ( ) {
freopen ( "tower.in", "r", stdin );
freopen ( "tower.out", "w", stdout );
scanf ( "%I64d", &n );
for ( int i = ; i <= n; i ++ )
scanf ( "%I64d", &h[i] ), pre[i] = pre[i-] + h[i];
for ( int i = ; i <= n; i ++ )
for ( int j = ; j < i; j ++ ) {
if ( pre[i] - pre[j] >= now[j] ) {
if ( dp[i] < dp[j] + ) dp[i] = dp[j] + , now[i] = pre[i] - pre[j];
else if ( dp[i] == dp[j] + ) {
now[i] = min ( now[i], pre[i] - pre[j] );
}
}
}
printf ( "%I64d", n - dp[n] );
return ;
}

显然(?)也是dp,$dp[i][j]$表示完成了$i$天,此时能力值为$j$时能做的最多工作量。$fine[i]$是预处理出的能力值为$i$时的效率最高的工作需要的时间。$qwq[i][j]$表示每个上完课后的第1天$i$,能力值为$j$,上课最短的时间。$pre[i]$表示过了$i$天可以得到的最大$dp$值。

枚举天数,能力值。

每次更新时可以选择不作为,即$dp[i][j]$直接从$dp[i-1][j]$转移过来。

如果第$i$天是某次刚上完课的第二天,则可以选择上课,从上课开始之前的最优$dp$值转移过来,即上课开始那一天的$pre$值。

如果当前天数和$fine[j]$满足可以工作,则从不工作那天转移过来,可以选择工作一次。

【注意】$dp$值初始化是负无穷,保证如果第$i$天不能满足$j$的能力值,则一定不会被更新,或去更新$pre$值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
using namespace std; int T, S, N, fine[], qwq[][], pre[], dp[][]; struct LRN {
int m, l, a;
} stdy[]; int main ( ) {
freopen ( "wrk.in", "r", stdin );
freopen ( "wrk.out", "w", stdout );
scanf ( "%d%d%d", &T, &S, &N );
memset ( qwq, 0x3f3f3f3f, sizeof ( qwq ) );
for ( RG int i = ; i <= S; i ++ ) {
int m, l, a;
scanf ( "%d%d%d", &m, &l, &a );
qwq[l+m][a] = min ( qwq[l+m][a], l );
}
memset ( fine, 0x3f3f3f3f, sizeof ( fine ) );
for ( RG int i = ; i <= N; i ++ ) {
int c, d;
scanf ( "%d%d", &c, &d );
fine[c] = min ( fine[c], d );
}
for ( int i = ; i <= ; i ++ )
fine[i] = min ( fine[i], fine[i-] );
memset ( dp, -0x3f3f3f3f, sizeof ( dp ) );
dp[][] = ;
for ( int i = ; i <= T; i ++ ) {
for ( int j = ; j <= ; j ++ ) {
dp[i][j] = dp[i-][j];
if ( qwq[i][j] != 0x3f3f3f3f ) dp[i][j] = max ( dp[i][j], pre[i-qwq[i][j]] );
if ( i - fine[j] >= ) dp[i][j] = max ( dp[i][j], dp[i-fine[j]][j] + );
pre[i] = max ( dp[i][j], pre[i] );
}
}
printf ( "%d", pre[T] );
return ;
}

很有趣的一道题。题目给出的性质是只有一个点的度数大于等于3,先找出这个点作为root。

bfs预处理出点距离的邻接矩阵,二分答案,每次去check的时候是选择root周围可以覆盖它的点,割掉这个点去更新答案。设当前枚举的点是$x$,先标记$x$可以覆盖的所有点,再dfs去计算没有被标记的点的数量,就是被拆分开的一条条链上的点的数量,每条链上需要的树洞是$ceil ( \frac{1.0 * now}{2*len+1} )$,$now$是这条链上的点数,注意因为自己也会算进去,所以一个点能覆盖的点数是$2*len+1$。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std; int n, m, k, root;
int dis[][], d[]; int stot, tov[], nex[], h[];
void add ( int u, int v ) {
tov[++stot] = v;
nex[stot] = h[u];
h[u] = stot;
} queue < int > q;
void bfs ( int s ) {
queue < int > q; q.push ( s );
while ( !q.empty ( ) ) {
int x = q.front ( ); q.pop ( );
for ( int i = h[x]; i; i = nex[i] ) {
int v = tov[i]; d[x] ++; d[v] ++;
if ( !dis[s][v] && v != s )
dis[s][v] = dis[s][x] + , q.push ( v );
}
}
} int now, v[]; void dfs ( int u ) {
now += ( v[u] = );
for ( int i = h[u]; i; i = nex[i] )
if ( !v[tov[i]] )
dfs ( tov[i] );
} int work ( int x, int len ) {
int s = ;
memset ( v, , sizeof ( v ) );
for ( int i = ; i <= n; i ++ )
v[i] = ( dis[i][x] <= len );
for ( int i = ; i <= n; i ++ )
if ( !v[i] ) now = , dfs ( i ), s += ceil ( 1.0 * now / ( * len + ) );
return s;
} bool check ( int x ) {
int ans = 0x3f3f3f3f;
for ( int i = ; i <= n; i ++ )
if ( dis[root][i] <= x ) {
ans = min ( ans, work ( i, x ) );
}
return ans < k;
} int main ( ) {
freopen ( "holes.in", "r", stdin );
freopen ( "holes.out", "w", stdout );
scanf ( "%d%d%d", &n, &m, &k );
for ( int i = ; i <= m; i ++ ) {
int x, y;
scanf ( "%d%d", &x, &y );
add ( x, y ); add ( y, x );
}
for ( int i = ; i <= n; i ++ ) {
bfs ( i );
if ( d[i] > ) root = i;
}
if ( !root ) {
cout << ceil ( 1.0 * ( n - k ) / ( k << ) );
return ;
}
int l = , r = n, ans;
while ( l <= r ) {
int mid = ( l + r ) >> ;
if ( check ( mid ) ) r = mid - , ans = mid;
else l = mid + ;
}
cout << ans;
return ;
}

【8.20校内测试】【DP】【二分+贪心】的更多相关文章

  1. 【8.23校内测试】【贪心】【线段树优化DP】

    $m$的数据范围看起来非常有问题??仔细多列几个例子可以发现,在$m<=5$的时候,只要找到有两行状态按位$&$起来等于$0$,就是可行方案,如果没有就不行. #include<i ...

  2. 2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解

    这次是zay神仙给我们出的NOIP模拟题,不得不说好难啊QwQ,又倒数了~ T1 大美江湖 这个题是一个简单的模拟题.   ----zay 唯一的坑点就是打怪的时候计算向上取整时,如果用ceil函数一 ...

  3. 【8.30校内测试】【找规律模拟】【DP】【二分+贪心】

    对于和规律或者数学有关的题真的束手无策啊QAQ 首先发现两个性质: 1.不管中间怎么碰撞,所有蚂蚁的相对位置不会改变,即后面的蚂蚁不会超过前面的蚂蚁或者落后更后面的蚂蚁. 2.因为所有蚂蚁速度一样,不 ...

  4. 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 题目大意: 给一棵树,n个节点,每条边有个权值,从每个点i出发有个不经过自己走过的点的最远距离 ...

  5. 【bzoj3312】[Usaco2013 Nov]No Change 状态压缩dp+二分

    题目描述 Farmer John is at the market to purchase supplies for his farm. He has in his pocket K coins (1 ...

  6. HDU-3681-Prison Break(BFS+状压DP+二分)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  7. 1. 线性DP 887. 鸡蛋掉落 (DP+二分)

    887. 鸡蛋掉落 (DP+二分) https://leetcode-cn.com/problems/super-egg-drop/ /*首先分析1个蛋,1个蛋的话,最坏情况需要N次,每次只能从0 1 ...

  8. HDU 3433 (DP + 二分) A Task Process

    题意: 有n个员工,每个员工完成一件A任务和一件B任务的时间给出,问要完成x件A任务y件B任务所需的最短时间是多少 思路: DP + 二分我也是第一次见到,这个我只能说太难想了,根本想不到. dp[i ...

  9. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

随机推荐

  1. thinkphp博客项目纪录

    项目地址:http://files.cnblogs.com/files/wordblog/blog.zip

  2. 阿里Java研发工程师实习面经,附面试技巧

    作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...

  3. perl6 一个猜测密码的注入

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $r = HTTP::Request.new; my $c = HTTP::Cookies. ...

  4. php隐藏WEBSHELL技巧

    把shell添加到网站logo图片里: cat logo.png shell.php > logo.png 在网站任意一个php文件里添加下面的最简单方法: fputs(fopen('/home ...

  5. weblogic nmap扫描脚本

     CVE-2018-2894 / Nmap利用脚本,可批量批量快速扫描getshell.检测漏洞.利用漏洞 地址:https://github.com/Rvn0xsy/nse_vuln/tree/ma ...

  6. linux shell 一些命令

    https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash wc: https: ...

  7. 在microsoft/dotnet:2.0.0-sdk中安装vim编辑器

    在Docker中安装了dotnetcore 2.0.0 的sdk,没有发现可用的编辑器,该sdk是基于debian:stretch构建的,以前没玩过debian,因为CentOS玩的多一些所以对vim ...

  8. 【C#日期系列(二)】--C#获取一段时间有多少个星期几

    #region 统计一段时间内有多少个星期几 ///<summary> ///统计一段时间内有多少个星期几 ///</summary> ///<param name=&q ...

  9. 【51nod】1244 莫比乌斯函数之和

    题解 求积性函数的前缀和?杜教筛! 这不给一发杜教筛入门必备之博客= = https://blog.csdn.net/skywalkert/article/details/50500009 好了,然后 ...

  10. Python爬虫-request的用法

    import requests if __name__ == '__main__': #基本用法 #response = requests.get("http://httpbin.org/g ...