#51nod上topcoder练习记
好久没刷51nod了,又听说topcoder有很多好题。那么就来51nod上刷吧。(那个客户端搞得有点烦(看不懂))
当图不连通的时候,答案为无穷大。
当图连通时,两个点之间的最大差值就是最短路长度乘上 $d$,跑floyd再看最短路的最大值即可。
#include <bits/stdc++.h> const int N = ;
const int INF = 0x3f3f3f3f; char s[N];
int mp[N][N], fa[N], n; int getfa(int x) {
return x == fa[x] ? x : fa[x] = getfa(fa[x]);
} void unit(int x, int y) {
x = getfa(x), y = getfa(y);
fa[x] = y;
} void floyd() {
for (int k = ; k <= n; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
mp[i][j] = std::min(mp[i][j], mp[i][k] + mp[k][j]);
} int main() {
int T;
scanf("%d", &T);
while (T--) {
int d;
scanf("%d%d", &n, &d);
for (int i = ; i <= n; i++) fa[i] = i;
for (int i = ; i <= n; i++) {
scanf("%s", s + );
for (int j = ; j <= n; j++) {
if (s[j] == 'Y' && i != j)
mp[i][j] = d, unit(i, j);
else if (i != j)
mp[i][j] = INF;
else
mp[i][j] = ;
}
}
int cnt = ;
for (int i = ; i <= n; i++)
if (getfa(i) == i) cnt++;
if (cnt > ) {
puts("-1");
continue;
}
floyd();
int ans = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
if (mp[i][j] < INF)
ans = std::max(ans, mp[i][j]);
printf("%d\n", ans);
}
return ;
}
可以发现当限制比数字的位置还大时,这个限制就没用了。
然后有时候到不了极限数据,因为被前面的卡住了或者被后面的卡住了。
即 $t_i - t_{i - 1} > x_i - x_{i - 1}$,$t_i - t_{i + 1} > x_{i + 1} - x_i$ 这两种情况。暴力更新即可。
然后最大值就在每两个限制之间得到。
#include <bits/stdc++.h> const int N = ; int x[N], t[N]; int main() {
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
int cnt = ;
x[cnt] = , t[cnt] = ;
for (int i = ; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
if (b < a - )
x[++cnt] = a, t[cnt] = b;
}
if (!cnt) {
printf("%d\n", n - );
continue;
}
for (int i = ; i <= cnt; i++) {
if (i > && t[i] - t[i - ] > x[i] - x[i - ])
t[i] = t[i - ] + x[i] - x[i - ];
if (i < cnt && t[i] - t[i + ] > x[i + ] - x[i]) {
t[i] = t[i + ] + x[i + ] - x[i];
i = ;
}
}
int ans = ;
for (int i = ; i < cnt; i++)
ans = std::max(ans, (t[i] + t[i + ] - x[i] + x[i + ]) / );
ans = std::max(ans, t[cnt] + n - x[cnt]);
printf("%d\n", ans);
}
}
一种球的贡献最多为 $2$,那么统计球的个数即可。
#include <bits/stdc++.h> const int N = ;
char s[N];
int cnt[]; inline int getid(char ch) {
if (ch == 'R') return ;
if (ch == 'G') return ;
return ;
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%s", s + );
int n = strlen(s + );
if (n == ) {
puts("");
continue;
}
if (n == ) {
puts("");
continue;
}
for (int i = ; i < ; i++)
cnt[i] = ;
for (int i = ; i <= ; i++)
cnt[getid(s[i])]++;
int ans = ;
for (int i = ; i <= n; i++) {
for (int j = ; j < ; j++)
ans += std::min(cnt[j], );
cnt[getid(s[i])]++;
}
printf("%d\n", ans);
}
return ;
}
和一个点会有交集的点最多只有 $k^2$ 个,特判这些点,再去其他点中最大的那个即可。
#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second const int N = ;
const int M = 1e4 + ;
int dx[], dy[];
char s[N];
int mp[N][N];
std::vector<int> belong[M];
std::pii p[M];
std::map<std::pii, int> gong; int main() {
freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--) {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = ; i <= n; i++) {
scanf("%s", s + );
for (int j = ; j <= m; j++)
mp[i][j] = s[j] - '';
}
for (int i = ; i <= k; i++)
scanf("%d%d", &dx[i], &dy[i]);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++) {
int pos = (i - ) * m + j;
p[pos].se = pos;
p[pos].fi = ;
for (int z = ; z <= k; z++) {
int x = i + dx[z], y = j + dy[z];
if (x <= || x > n || y <= || y > m) continue;
belong[(x - ) * m + y].push_back(pos);
p[pos].fi += mp[x][y];
}
}
int ans = ;
std::sort(p + , p + n * m + , std::greater<std::pii>());
for (int cnt = ; cnt <= n * m; cnt++) {
gong.clear();
int pos = p[cnt].se;
int i = pos / m, j = pos % m;
if (!j) j = m;
else i++;
if (p[cnt].fi + p[].fi <= ans) continue;
for (int z = ; z <= k; z++) {
int x = i + dx[z], y = j + dy[z];
if (x <= || x > n || y <= || y > m) continue;
int ne = (x - ) * m + y;
for (int tong: belong[ne]) {
if (pos == tong) continue;
gong[std::pii(std::min(pos, tong), std::max(pos, tong))] -= mp[x][y];
}
}
for (int z = ; z <= k * k + ; z++) {
if (z == cnt) continue;
int id = p[z].se;
ans = std::max(ans, gong[std::pii(std::min(pos, id), std::max(pos, id))] + p[cnt].fi + p[z].fi);
if (!gong.count(std::pii(std::min(pos, id), std::max(pos, id)))) break;
}
}
for (int i = ; i <= n * m; i++)
belong[i].clear(), p[i].fi = p[i].se = ;
printf("%d\n", ans);
}
return ;
}
唉,这都想不出来,好菜啊...
$i$ 到 $j$ 的代价就等于第 $i$ 行 $0$ 到 $j - 1$ 有多少个 'Y'。要优先走这条边就要付出这么多代价,然后floyd就好了
#include <bits/stdc++.h> const int N = ;
const int INF = 0x3f3f3f3f;
int mp[N][N];
char s[N]; int main() {
int T;
scanf("%d", &T);
while (T--) {
memset(mp, 0x3f, sizeof mp);
int n;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%s", s + );
int cost = ;
for (int j = ; j <= n; j++)
if (s[j] == 'Y')
mp[i][j] = cost++;
}
for (int i = ; i <= n; i++)
mp[i][i] = ;
for (int k = ; k <= n; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
mp[i][j] = std::min(mp[i][j], mp[i][k] + mp[k][j]);
printf("%d\n", mp[][n] == INF ? - : mp[][n]);
}
return ;
}
当取的 $low$ 值之和不小于 $x$ 时,为一个方案
当不取的 $high$ 值之和不大于 $c - x$ 时,为一个方案
这两种情况可以独立来算,对 $low$ 和 $high$ 分别排个序就ok了。
#include <bits/stdc++.h> const int N = ; int low[N], high[N]; int main() {
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--) {
int n, c, x;
scanf("%d%d%d", &n, &c, &x);
for (int i = ; i <= n; i++)
scanf("%d%d", low + i, high + i);
int ans = n;
std::sort(low + , low + + n);
std::sort(high + , high + + n);
for (int i = n, sum = ; i; i--) {
sum += low[i];
if (sum >= x) {
ans = std::min(n - i + , ans);
break;
}
}
for (int i = , sum = ; i <= n; i++) {
sum += high[i];
if (c - sum < x) {
ans = std::min(ans, n - i + );
break;
}
}
printf("%d\n", ans);
}
return ;
} /***
34
32
28
***/
当不出现问号时,该开时开,该关时关就OK了。
当出现了问号时,如果上一轮的该位置状态为 '-' 且这一轮有开灯的操作,那么这一位就可以是 '?',或者该位置状态为 '+' 且这一轮有关灯的操作,同理也是 '?'
多一个 '?' 就可以让之后尽量少操作。
#include <bits/stdc++.h> const int N = ;
char mp[N][N], s[N]; int main() {
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
scanf("%s", mp[i] + );
for (int i = ; i <= m; i++)
s[i] = '-';
int ans = ;
for (int i = ; i <= n; i++) {
bool open = , close = ;
for (int j = ; j <= m; j++) {
if (s[j] == '-' && mp[i][j] == '+')
open = ;
if (s[j] == '+' && mp[i][j] == '-')
close = ;
}
if (open) ans++;
if (close) ans++;
ans++;
for (int j = ; j <= m; j++) {
if (mp[i][j] == '?') {
if (close && s[j] == '+')
s[j] = '?';
if (open && s[j] == '-')
s[j] = '?';
} else {
s[j] = mp[i][j];
}
}
}
printf("%d\n", ans);
}
return ;
}
答案最多为 3,为 3 时即存在奇环,bfs判一下即可。
#include <bits/stdc++.h> const int N = ;
const int dir[][] = {{-, }, {-, }, {, }, {, }, {, -}, {, -}};
char s[N][N];
int n, dis[N][N]; bool bfs(int dx, int dy) {
std::queue< std::pair<int, int> > que;
que.push(std::pair<int, int>(dx, dy));
while (!que.empty()) {
std::pair<int, int> p = que.front(); que.pop();
int i = p.first, j = p.second;
for (int k = ; k < ; k++) {
int x = i + dir[k][], y = j + dir[k][];
if (x < || y < || x > n || y > n || s[x][y] == '-') continue;
if (dis[x][y]) {
if (dis[x][y] % == dis[i][j] % ) return true;
continue;
}
que.push(std::pair<int, int>(x, y));
dis[x][y] = dis[i][j] + ;
}
}
return false;
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
int ans = ;
for (int i = ; i <= n; i++) {
scanf("%s", s[i] + );
for (int j = ; j <= n; j++)
if (s[i][j] == 'X') ans = ;
}
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++) if (s[i][j] == 'X') {
for (int k = ; k < ; k++) {
int x = i + dir[k][], y = j + dir[k][];
if (x < || y < || x > n || y > n || s[x][y] == '-') continue;
ans = ;
}
}
memset(dis, , sizeof(dis));
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
if (s[i][j] == 'X' && dis[i][j] == )
if (bfs(i, j)) ans = ;
printf("%d\n", ans);
}
return ;
}
#51nod上topcoder练习记的更多相关文章
- 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛
OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...
- -bash: 无法为立即文档创建临时文件: 设备上没有空间---记一次报错
故障发生原因 测试环境,之前用该机器做过docker-compose,后来有需要用到该机器上的docker环境,需要将旧的docker容器全部删除,由于之前启动是使用docker-compose启动的 ...
- 几道51nod上据说是提高组难度的dp题
1409 加强版贪吃蛇 听着懵逼做着傻逼. 每个格子只能经过一次,穿过上下界答案清0,不考虑穿的话就随便dp.如果要穿就是从尽可能上面的位置穿过上界,尽可能下面的位置穿过下界. 那么转移这一列之前找一 ...
- GitHub上传家庭记账本
GitHub的使用参考之前的博客GitHub的初步了解和使用,并完成了相关的android个人家庭记账本的上传
- mac上安装brew----笔记
一.mac 终端下,执行以下命令,即可安装brew: 介绍brew:是Mac下的一款包管理工具brew [brew install 软件],类似与centos里面的 yum[yum install 软 ...
- 51Nod 快速傅里叶变换题集选刷
打开51Nod全部问题页面,在右边题目分类中找到快速傅里叶变换,然后按分值排序,就是本文的题目顺序. 1.大数乘法问题 这个……板子就算了吧. 2.美妙的序列问题 长度为n的排列,且满足从中间任意位置 ...
- [日常] PKUWC 2018爆零记
吃枣药丸...先开个坑... day -1 上午周测...大翻车... 下午被查水表说明天必须啥啥啥...(当时我差点笑出声) 晚上领到笔记本一枚和一袋耗材(袜子) 然而班会开太晚回去没来得及收拾就晚 ...
- 51Nod 最小公倍数之和V3
这题公式真tm难推……为了这题费了我一个草稿本…… woc……在51Nod上码LaTeX码了两个多小时…… 一开始码完了前半段,刚码完后半段突然被51Nod吃了,重新码完后半段之后前半段又被吃了,吓得 ...
- 51Nod 1815 调查任务
发现绍一的人很喜欢做51nod,不得不说这还是一个很全能的良心OJ 但是做的这道题就一点都不良心了,简直是毒瘤,调了一早上 首先我们考虑让一条路径的\(a_x\ mod\ a_y\)的值最大,我们简单 ...
随机推荐
- java web开发入门八(ssm整合)基于intellig idea
ssm整合 一.导入相关包 二.开发流程 1.写entity package com.eggtwo.euq.entity; import java.io.Serializable; import ja ...
- 工作中常用的Linux命令介绍与实践
前言 做后端开发的同学,一般都会接触到服务器,而我们现在的系统用的比较多的服务器系统就是linux了,平时多多少少也会接触到一些linux下的shell命令.我们来介绍下linux一些常用的命令和使用 ...
- Python爬取豆瓣电影top
Python爬取豆瓣电影top250 下面以四种方法去解析数据,前面三种以插件库来解析,第四种以正则表达式去解析. xpath pyquery beaufifulsoup re 爬取信息:名称 评分 ...
- k8s本地部署
k8s是什么 Kubernetes是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署.自动扩缩容.维护等功能. Kubernetes 具有如下特点: 便携性: 无论公有云.私有云.混合 ...
- Qt Quick 基本元素初体验
Qt Quick 作为 QML 语言的标准库,提供了很多基本元素和控件来帮助我们构建 Qt Quick 应用,这节我们简要地介绍一些 Qt Quick 元素. 一. 基本可视化项 1.1 Item I ...
- Linux : Nginx相关
nginx安装参考链接: https://www.cnblogs.com/kaid/p/7640723.html 自定义编译目录: https://blog.csdn.net/ainuser/arti ...
- 9、VUE过渡和动画
1.过渡效果 Vue提供了transition的封装组件,在下列情形中,可以给任何元素和组件添加entering/leaving过渡. 我们注意到,<transition>标签的标记是 n ...
- asp.net chart美化+绑定数据--饼图
asp.net chart之饼图 开发环境VS2010 chart控件是vs自带控件 前台: <asp:Chart ID="Chart3" runat="serve ...
- JavaScript学习思维导图
JS基本概念 JS操作符 JS基本语法 JS数组 JS Date用法 JS 字符串用法 JS编程风格 JS实践
- 华为手机usb调试打开后自动关闭怎么办?华为手机 usb调试为什么自动关闭?usb调试老是自动关闭怎么回事?
01 解决方法一依次点击“设置”——“系统”——“开发人员选项”先开启“开发者选项”开关. 02 然后在开启“USB调试”开关后,一并将“'仅充电'模式下允许ADB调试”选项开关打开.这样,华为手机u ...