P1273 有线电视网

题目描述

某收费有线电视网计划转播一场重要的足球比赛。他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点。

从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和。

现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号。

写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多。

输入输出格式

输入格式:

输入文件的第一行包含两个用空格隔开的整数N和M,其中2≤N≤3000,1≤M≤N-1,N为整个有线电视网的结点总数,M为用户终端的数量。

第一个转播站即树的根结点编号为1,其他的转播站编号为2到N-M,用户终端编号为N-M+1到N。

接下来的N-M行每行表示—个转播站的数据,第i+1行表示第i个转播站的数据,其格式如下:

K A1 C1 A2 C2 … Ak Ck

K表示该转播站下接K个结点(转播站或用户),每个结点对应一对整数A与C,A表示结点编号,C表示从当前转播站传输信号到结点A的费用。最后一行依次表示所有用户为观看比赛而准备支付的钱数。

输出格式:

输出文件仅一行,包含一个整数,表示上述问题所要求的最大用户数。

输入输出样例

输入样例#1: 复制

5 3
2 2 2 5 3
2 3 2 4 3
3 4 2

输出样例#1: 复制

2

说明

样例解释

如图所示,共有五个结点。结点①为根结点,即现场直播站,②为一个中转站,③④⑤为用户端,共M个,编号从N-M+1到N,他们为观看比赛分别准备的钱数为3、4、2,从结点①可以传送信号到结点②,费用为2,也可以传送信号到结点⑤,费用为3(第二行数据所示),从结点②可以传输信号到结点③,费用为2。也可传输信号到结点④,费用为3(第三行数据所示),如果要让所有用户(③④⑤)都能看上比赛,则信号传输的总费用为:

2+3+2+3=10,大于用户愿意支付的总费用3+4+2=9,有线电视网就亏本了,而只让③④两个用户看比赛就不亏本了。

题解:裸的树上背包,和树上染色差不多:https://www.cnblogs.com/EdSheeran/p/9353225.html

#include<bits/stdc++.h>
using namespace std;
const int M = 3005;
const int inf = -1e8;
int h[M], siz[M], val[M], tot, dp[M][M], dep[M];
int n, m;
struct edge{int v, nxt, w;}G[M << 2];
void add(int u, int v, int w){G[++tot].v = v; G[tot].w = w; G[tot].nxt = h[u]; h[u] = tot;
}void dfs(int u, int f){dp[u][0] = 0;for(int i = h[u]; i; i = G[i].nxt){int v = G[i].v;if(v == f)continue;dfs(v, u);siz[u] += siz[v];for(int q = siz[u]; q; q--)for(int p = min(siz[v], q); p; p--){if(dp[u][q - p] > inf)dp[u][q] = max(dp[u][q], dp[u][q - p] + dp[v][p] - G[i].w);}}if(u > n - m){siz[u] = 1;dp[u][1] = val[u];}//printf("\n%d ",u);//for(int i = 0; i <= n; i++)printf("%d ", dp[u][i]);
}int main(){scanf("%d%d", &n, &m);memset(dp, 0x8f, sizeof(dp));int x, u, v, w;for(int i = 1; i <= n - m; i++){scanf("%d", &x);while(x--){scanf("%d%d", &v, &w);add(i, v, w);///add(v, u, w);
        }}for(int i = n - m + 1; i <= n; i++)scanf("%d", val + i);dfs(1, 0);int ans = 0;for(int v = m; v; v--)if(dp[1][v] >= 0){ans = v;break;}printf("%d\n", ans);
}
/*
8 4
2 2 2 4 5
2 3 4 7 2
2 5 4 6 5
1 8 7
2 3 9 12
*/

View Code

P1169 [ZJOI2007]棋盘制作

题目描述

国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。

而我们的主人公小Q,正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则。

小Q找到了一张由N×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。

不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。

于是小Q找到了即将参加全国信息学竞赛的你,你能帮助他么?

输入输出格式

输入格式:

包含两个整数NN和MM,分别表示矩形纸片的长和宽。接下来的NN行包含一个N ×M的0101矩阵,表示这张矩形纸片的颜色(00表示白色,11表示黑色)。

输出格式:

包含两行,每行包含一个整数。第一行为可以找到的最大正方形棋盘的面积,第二行为可以找到的最大矩形棋盘的面积(注意正方形和矩形是可以相交或者包含的)。

输入输出样例

输入样例#1: 复制

3 3
1 0 1
0 1 0
1 0 0

输出样例#1: 复制

4
6

说明

对于20\%20%的数据,N, M ≤ 80N,M≤80

对于40\%40%的数据,N, M ≤ 400N,M≤400

对于100\%100%的数据,N, M ≤ 2000N,M≤2000

题解:一道毒瘤单调栈,我们可以预处理(i,j)向上最多扩张多少个,当第(i, j)确定后,若(i + 1, j)和他不同,那他上面合法部分一定与i的部分互异(这是此题关键);

然后就变成了一个求01最大自矩阵的O(N*M)的单调栈算法了;模版:https://www.cnblogs.com/EdSheeran/p/8459824.html

#include<bits/stdc++.h>
using namespace std;
const int M = 1005;
struct Maxtri{int h, w, id;}tp[M];
bool a[M][M];
int up[M][M], t;
int pf(int a){return a*a;}
int main(){int n, m, ans = 0, ans2 = 0;scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++){scanf("%d", &a[i][j]);}for(int i = 1; i <= m; i++)up[n][i] = 1;for(int i = n - 1; i; i--)for(int j = 1; j <= m; j++)up[i][j] = (a[i][j] ^ a[i + 1][j]) ? up[i + 1][j] + 1 : 1;for(int i = 1; i <= n; i++){t = 0;for(int j = 1; j <= m; j++){int w = 0;if(a[i][tp[t].id] ^ a[i][j] == 0)while(t){w += tp[t].w;ans = max(ans, w * tp[t].h);ans2 = max(ans2, pf(min(tp[t].h, w)));t--;}w = 0;if(tp[t].h > up[i][j]){while(t && tp[t].h > up[i][j]){w += tp[t].w;ans = max(ans, w * tp[t].h);ans2 = max(ans2, pf(min(tp[t].h, w)));t--;}}tp[++t].h = up[i][j], tp[t].id = j, tp[t].w = w + 1;w = 0;if(j == m && t){while(t){w += tp[t].w;ans = max(ans, w * tp[t].h);ans2 = max(ans2, pf(min(tp[t].h, w)));t--;}    }}}printf("%d\n%d\n", ans2, ans);
}

View Code

P2577 [ZJOI2005]午餐

题目描述

上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。

THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。

现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。

假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。

现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。

输入输出格式

输入格式:

第一行一个整数N,代表总共有N个人。

以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。

输出格式:

一个整数T,代表所有人吃完饭的最早时刻。

输入输出样例

输入样例#1: 复制

5
2 2
7 7
1 3
6 4
8 5

输出样例#1: 复制

17

说明

所有输入数据均为不超过200的正整数。

题解:贪心+DP;一道好题;

首先顺序的确定是按吃饭时间的大在前确定的,DP考虑在1、2号窗口吃饭;

dp[i][j] 表示第i个人打完饭,在1号窗口总的打饭时间为 j 的最早结束时间;

如果他在一号窗口,就是 max(dp[i][j - p[i].a], j + p[i].b),可能是之前的时间更慢,也可能当前的最慢;

同理,在二号窗口,就是max(dp[i][j], sum[i] - j + p[i].b),这个我们可以通过一个前缀和确定二号的时间;

然后两者取min

#include<bits/stdc++.h>
using namespace std;const int M = 205;
struct Point{int a, b;}p[M];
bool cmp(Point s, Point t){return s.b > t.b;
}
int dp[M][M*M], sum[M];int main(){int n, ans = 1e9;scanf("%d", &n);for(int i = 1; i <= n; i++)scanf("%d%d", &p[i].a, &p[i].b);sort(p + 1, p + 1 + n, cmp);for(int i = 1; i <= n; i++)sum[i] = sum[i - 1] + p[i].a;memset(dp, 127, sizeof(dp));dp[0][0] = 0;for(int i = 1; i <= n; i++)for(int j = 0; j <= sum[i]; j++){dp[i][j] = max(dp[i - 1][j], sum[i] - j + p[i].b);if(j >= p[i].a) dp[i][j] = min(dp[i][j], max(dp[i - 1][j - p[i].a], j + p[i].b));}for(int i = 0; i <= sum[n]; i++)ans = min(ans, dp[n][i]);printf("%d\n", ans);}

View Code

P2051 [AHOI2009]中国象棋

题目描述

这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

输入输出格式

输入格式:

一行包含两个整数N,M,之间由一个空格隔开。

输出格式:

总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。

输入输出样例

输入样例#1: 复制

1 3

输出样例#1: 复制

7

说明

样例说明

除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。

数据范围

100%的数据中N和M均不超过100

50%的数据中N和M至少有一个数不超过8

30%的数据中N和M均不超过6

题解:此题关键是当前行与上一行的状态无关,这样就和以往的DP不同;

一行、一列最多放2个炮,影响这行的是之前每列放了多少个炮;

dp[i][j]表示有i列放了1个, j列放了2个;

然后转移就是细节比较多的分类讨论+数学计算;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 9999973;
ll dp[105][105][105];
inline ll moc(ll a){return a >= mod ? a - mod : a;}
int main(){int n, m;ll ans = 0;scanf("%d%d", &n, &m);int u = 0;dp[0][0][0] = 1;for(int k = 0; k < n; k++){memset(dp[u^1], 0, sizeof(dp[u^1]));for(int j = 0; j <= m; j++)for(int i = 0; i <= m - j; i++)if(dp[u][i][j]){ll t = dp[u][i][j];dp[u^1][i][j] = moc(dp[u^1][i][j] + t);if(m-i-j > 0) dp[u^1][i+1][j] = moc(dp[u^1][i+1][j] + t * 1LL*(m-i-j) % mod);if(m-i-j > 1) dp[u^1][i+2][j] = moc(dp[u^1][i+2][j] + t * 1LL*(m-i-j)*(m-i-j-1)/2 % mod);if(i)          dp[u^1][i-1][j+1] = moc(dp[u^1][i-1][j+1] + t * 1LL*i % mod);if(i > 1)      dp[u^1][i-2][j+2] = moc(dp[u^1][i-2][j+2] + t * 1LL*i*(i-1)/2 % mod);if(m-i-j && i) dp[u^1][i][j+1] = moc(dp[u^1][i][j+1] + t * 1LL*(m-i-j)*i % mod);}u ^= 1;}for(int j = 0; j <= m; j++)for(int i = 0; i <= m - j; i++)ans = (ans + dp[u][j][i]) % mod;//, printf("%d %d %lld\n",i,j,dp[u][i][j]);printf("%lld\n", ans);
} 

View Code

转载于:https://www.cnblogs.com/EdSheeran/p/9757579.html

洛谷试炼场 动态规划TG.lv(2)相关推荐

  1. 洛谷 - 试炼场(全部题目备份)

    整理的算法模板合集: ACM模板 目录 1.新手村 1 - 1 洛谷的第一个任务 1 - 2 顺序与分支 1 - 3 循环!循环!循环! 1 - 4 数组 1 - 5 简单字符串 1 - 6 过程函数 ...

  2. 【OJ】洛谷试炼场の新手村整合(Java语言描述)

    Pass 最近通关了洛谷试炼场新手村Part,做了很多的红题和橙题,这里做一下整理吧,希望对需要的人有所帮助. 说明 这些内容确实不是什么复杂的东西,所以无需多言. 洛谷的第一个任务 这里是我写的所有 ...

  3. 洛谷试炼场-简单数学问题-二分查找

    洛谷试炼场-简单数学问题 P1147 连续自然数和 题解: 本题给定一个数n,求连续自然数的和为n,用一个前缀数组,low_bound,upper_bound,查找是否是同一个数.O(nlog(n)) ...

  4. 洛谷试炼场 P1553 数字反转(升级版)题解

    洛谷试炼场 P1553 数字反转(升级版)题解 [c] 题目描述 给定一个数,请将该数各个位上数字反转得到一个新数. 这次与NOIp2011普及组第一题不同的是:这个数可以是小数,分数,百分数,整数. ...

  5. 洛谷试炼场 4-8单调队列

    layout: post title: 洛谷试炼场 4-8单调队列 author: "luowentaoaa" catalog: true mathjax: true tags: ...

  6. 【洛谷试炼场】普及练习场——排序Ex

    题目 1.P1583魔法照片 排序 题目链接· 蒟蒻题解 2.P1051谁拿了最多奖学金[NOIP2005T1] 排序 题目链接 蒟蒻题解 3.P1093奖学金[NOIP2007普及] 排序 题目链接 ...

  7. 小a和uim之大逃离,洛谷之提高历练地,动态规划TG.lv(1)(3-2)

    正题 第二题:小a和uim之大逃离 这题有点烦,但是我们可以从k入手,大小为k的魔瓶,可以装的容量为0到k,那么相当于我们每一次mod 一下k 就行了. 我们当然也可以从小a和小uim的魔瓶差入手,我 ...

  8. 洛谷P2255 动态规划

    一种dp的解法 首先对于每一个节目都是看与不看的问题,可以选择对开始时间排序后,按顺序考虑每一个节目,排序后优秀的地方在于,你考虑一个节目的时候,最优解的选取方法里,在你当前节目之前会选取到的节目都是 ...

  9. 洛谷试炼场被虐记录——新手村

    https://www.luogu.org/training/mainpage P1217 [USACO1.5] 回文质数 https://www.luogu.org/problemnew/show/ ...

最新文章

  1. Keras Lambda层
  2. 模型量化--TBN:Convolutional Neural Network with Ternary Inputs and Binary Weights
  3. java并发环境安全初始化
  4. 《剑指Offer》题一~题十
  5. roads 用户体验标准_世界智能大会与ROAD用户体验报告
  6. Cloud一分钟 |高通预在年底与苹果和解;比特币绝地反弹;广电拿下5G,或成第四大运营商...
  7. 加投35000瓶原价茅台 天猫双11今晚8点开售
  8. ​香农与信息论三大定律
  9. jsp统计页面访问量和刷访问量的简单使用
  10. dw注册页面html,在 Dreamweaver 中生成注册页 - Dreamweaver 用户指南
  11. leetcode 寻找峰值
  12. 手机里tencent文件夹能删吗_手机上的文件夹能不能删?看完之后秒懂
  13. 4年小Java的心路历程,绝对干货分享
  14. centOS6.5中部署java调用h2o中python包环境
  15. 【资讯】德勤在香港成立区块链实验室
  16. 20 个好用的 Web API
  17. 曲神的hu测 T2.Van(左偏树+dp)T3.Gay
  18. 在前端页面中调用本机的摄像头
  19. u盘raw怎么恢复其中的数据
  20. Linux系统bond模式原理与配置

热门文章

  1. BootStrap 4种图片形式 image形式 img-rounded img-circle img-thumbnail img-responsive
  2. vue移动端的真机测试
  3. 【笔记整理】jq笔记
  4. android hdmi拔插广播,Android_8.1插拔hdmi后,音量会变到最大
  5. 用友U9 UFSoft.UBF.Business.Session
  6. 单片机C语言GRB888和RGB565的互相转换
  7. Python 实现英文新闻摘要自动提取 1
  8. 好书推荐-——《态度》——吴军老师著
  9. 7-22 龟兔赛跑 (超简单详细思路)
  10. ERROR: Cannot uninstall ‘filelock‘. It is a distutils installed project and thus we cannot accuratel