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

所以正解是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. ckeditor+ckfinder+java

    (java)Ckdeitor+ckfinder整合 第一步:工具下载 首先下载:CKEditor 地址:http://cdeditor.com/dowmload 接着下载CKFinder 地址:htt ...

  2. spring mvc 自定义编辑器

    起始知识: Java标准的PropertyEditor的核心功能是将一个字符串转换为一个Java对象,以便根据界面的输入或配置文件中的配置字符串构造出一个JVM内部的java对象. 如何注册自定义的属 ...

  3. nginx 各种配置

    first : mkdir /usr/local/nginx/conf/vhosts{网站配置}/usr/local/nginx/conf/vhosts/test.conf : server { li ...

  4. ACM——【百练习题备忘录】

    1. 在做百练2807题:两倍时,错将判断语句写成 a/b ==2,正确写法是:a == b*2 因为C/C++int型做除法时自动舍入,如:5/2 == 2,但是 5 =/= 2*2. 2. 在做百 ...

  5. python抓取链家房源信息(二)

    试着用scrapy将之前写的抓取链家网信息的重新写了写 然后先是用了第一页的网页作为测试,调试代码,然后发现总是抓取的时候遇见了 类似于这样的问题,并且抓取不到信息 2017-03-28 17:52: ...

  6. 最直白、最易懂的话带你认识和学会---数据分析基础包之numpy的使用

    前言 numpy是一个很基础很底层的模块,其重要性不言而喻,可以说对于新手来说是最基础的入门必须要学习的其中之一.在很多数据分析,深度学习,机器学习亦或是人工智能领域的模块中,很多的底层都会用到这个模 ...

  7. csu 1553(RMQ+尺取法)

    1553: Good subsequence Time Limit: 2 Sec  Memory Limit: 256 MBSubmit: 794  Solved: 287[Submit][Statu ...

  8. Linux 用户篇——用户管理命令之useradd、passwd、userdel、usermod

    一.用户重要,用户管理命令同样重要 用户是Linux系统安全的核心,每个登录Linux系统的用户都会分配相应的权限,这些权限取决于能否访问系统中各种对象.而管理这些用户的相关信息离不开用户管理命令,比 ...

  9. mysql建立自增主键的插入,及自动插入当前时间

    MYSQL里用这两个字段,几乎都是必须的. 以前都是自动建立的,现在手把手建立的时候,就要找资料来搞定了. 参考URL: http://blog.csdn.net/Weicleer/article/d ...

  10. IEEEXtreme 10.0 - Full Adder

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - Full Adder 题目来源 第10届IEEE极限编程大赛 https://www.hackerrank. ...