【解题报告】Codeforces Round #354 (Div. 2)

2024-04-22 04:08

本文主要是介绍【解题报告】Codeforces Round #354 (Div. 2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接


A. Nicholas and Permutation(Codeforces 676A)

思路

显然,将最大值或最小值中的一个交换到数组的某一端(若不放在端点上,则放在更靠近端点的位置总能得到更优的解)能让最大值与最小值之间的距离最大。我们可以通过计算计算出最优的方法。但是因为只有四种组合(最小值最左,最小值最右,最大值最左,最大值最右),所以可以直接枚举组合,并更新最优解。

代码
#include <cstdio>
#include <algorithm>
using namespace std;const int maxn = 110;
int n, b, c, minIdx, maxIdx, a[maxn];int abs(int x) {return x > 0 ? x : -x;
}int main() {scanf("%d", &n);for(int i = 1; i <= n; i++) {scanf("%d", &a[i]);if(a[i] == 1) {minIdx = i;}if(a[i] == n) {maxIdx = i;}}b = max(abs(minIdx - n), abs(minIdx - 1));c = max(abs(maxIdx - n), abs(maxIdx - 1));printf("%d\n", max(b, c));return 0;
}

B.Pyramid of Glasses(Codeforces 676B)

思路

因为 n10 ,所以酒杯的数量 num55 (等差数列求和)。这样的数量足以让我们用暴力的方法解决此题。首先最暴力的办法是每次往最顶端的酒杯倒一杯酒,然后就循环或递归访问每个酒杯,以计算出每个酒杯的酒的余量。其次比较不那么暴力的方法是一次性把所有的酒倒进最顶端的酒杯中,然后也是循环或递归访问每个酒杯,以计算出每个酒杯的余量。显然,相比之下,不论在时间复杂度还是在实现复杂度上,后者会优于前者。但前者更容易被想到。

代码
#include <bits/stdc++.h>
using namespace std;const int maxn = 15;
const double eps = 1e-10;
int n, t, cnt;
double h[maxn][maxn];int cmp(double x) {return x < - eps ? -1 : x > eps;
}void dfs(int x, int y, double come) {if(x > n) {return;}if(cmp(come) == 0) {return;}if(cmp(h[x][y] - 1) == 0) {dfs(x + 1, y, come / 2);dfs(x + 1, y + 1, come / 2);        }else {if(cmp(h[x][y] + come - 1) < 0) {h[x][y] += come;}else {int to = h[x][y] + come - 1;cnt++;h[x][y] = 1;dfs(x + 1, y, to / 2);dfs(x + 1, y + 1, to / 2);}}
}int main() {scanf("%d%d", &n, &t);cnt = 0;while(t--) {dfs(1, 1, 1.0);}printf("%d\n", cnt);return 0;
}

C. Vasya and String(Codeforces 676C)

思路

刚开始一直往动态规划那方面想,所以浪费了不少时间。但实际上本题从“枚举子串”的方面想才是对的(看来凡事还是先上暴力思维会比较不容易走偏)。我们可以先以 O(n2) 的复杂度枚举出子串,然后以 O(n) 的复杂度计算出该子串是否能通过 k 次“改变”变成字符统一的字符串。在枚举中更新满足条件的子串的最大长度即可。但是 O(n3) 的总复杂度是不发承受的,那么我们能不能仅 O(n) 地扫描一遍字符串就完成上述全部工作呢?事实上是可以的。假如 s 的子串 s[p..q] 是满足条件的字符串,而 s[p..q+1] 是不满足条件的字符串,那么下一步应当是令 p=p+1 q=p (枚举以新的 p 开头的子串)。实际上,这样使得集合 {s[p+1..j],p+1jq} 中的全部字符串都重复枚举了(因为不可能得到更优解)。也就是说尾指针 q 的回溯是没必要的。这种利用无法达到最优解的特性避免回溯尾指针的枚举子串的方法就是“尺取法”(名字取自《挑战程序设计竞赛》)。这样我们用 O(n) 的复杂度枚举子串,然后在头尾指针移动的过程中动态更新子串中 a 的数量 sa b 的数量 sb (因为“尺取法”有每次只用让指针移动一个字符),根据 min(sa,sb) k 的关系来判断子串是否满足条件并更新答案,题目得解。

代码

#include <bits/stdc++.h>
using namespace std;const int maxn = 1e5 + 5;
char s[maxn];
int n, k, l, r, sa, sb, ans = 0;int main() {scanf("%d%d%s", &n, &k, s);sa = (s[l=0] == 'a');sb = (s[r=0] == 'b');while(r < n) {if(sa <= k || sb <= k) {ans = max(ans, r - l + 1);}else {sa -= (s[l] == 'a');sb -= (s[l++] == 'b');}sa += (s[++r] == 'a');sb += (s[r] == 'b');        }printf("%d\n", ans);return 0;
}

D. Theseus and labyrinth(Codeforces 676D)

思路

若没有方块的旋转,则这个问题就是简单的用 BFS 求最短步数的问题。现在有了旋转,相当于总共有 4 n×m 的网格,分别对应着原来的网格不旋转 (s=0) ,旋转 1 (s=1) ,旋转 2 (s=2) 和旋转 3 (s=3) 的情况。那么我们可以将这 4 个网格看成三维的网格,也就是说可以将状态空间看成 n×m×4 的三维空间。那么主人公处在某个状态 (x,y,s) 的时候可以向五个方向移动,分别为上 (x1,y,s) ,下 (x+1,y,s) ,左 (x,y1,s) ,右 (x,y+1,s) 和旋转1次 (x,y,(s+1)mod4) ,而且每次移动的代价都是相同的(等待 1 秒)。设计好状态以后在三维空间内用 BFS 求最短步数即可。另外还有一个小问题,就是如何简洁而快速地判断是否能向某个方向移动。我们可以建立一个映射 b[u]=v ,表示当方块里的内容为 u 时,向上右下左(不是上下左右)四个方向移动是否可行(将四个方向的信息压缩成整数 v ),为此我们要将上右下左四个方向分别编号为 0,1,2,3 。例如 b[+]=15 (二进制表示为 1111 )表示当方块的内容为 + 时上右下左四个方向都能移动。 b[>]=1<<2 (二进制表示为 0010 )表示只能向右移动,为什么要向左移动2位呢?因为“右”的编号为 2 <script id="MathJax-Element-440" type="math/tex">2</script> 。这样,知道了方方块内的内容和移动的方向就能知道向这个方向移动是否可行。

代码
#include <bits/stdc++.h>
using namespace std;// 搜索树中的节点
struct node {int x, y, s, d;node(int x, int y, int s, int d): x(x), y(y), s(s), d(d) {}
};const int maxn = 1010;
// 上右下左四个方向的坐标变化 
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
// 判重用的数组
bool vis[maxn][maxn][5];
char G[maxn][maxn];
int n, m, sx, sy, tx, ty, b[150];
queue <node> q;// 初始化映射
void init() {b['^'] = 1 << 0;b['>'] = 1 << 1;b['v'] = 1 << 2;b['<'] = 1 << 3;b['L'] = ~b['<'];b['R'] = ~b['>'];b['U'] = ~b['^'];b['D'] = ~b['v'];b['-'] =  b['<'] | b['>'];b['|'] =  b['^'] | b['v'];b['+'] =  b['|'] | b['-'];
}// 状态的转移
void expand(node& u, int dir) {int x, y, s, d, i, j;if(dir == -1) {x = u.x;y = u.y;s = (u.s + 1) % 4;d = u.d + 1;if(vis[x][y][s]) {return;}q.push(node(x, y, s, d));vis[x][y][s] = true;}else {// 判断本方块往dir方向是否有通路i = b[G[u.x][u.y]];j = 1 << ((dir - u.s + 4) % 4);if((i & j) == 0) {return;}x = u.x + dx[dir];y = u.y + dy[dir];s = u.s;d = u.d + 1;// 防止访问越界if(x < 1 || x > n || y < 1 || y > m) {return;}// BFS的判重if(vis[x][y][s]) {return;}// 判断新方块的dir方向的反方向是否有通路i = b[G[x][y]];j = 1 << ((dir + 2 - s + 4) % 4);if((i & j) == 0) {return;}q.push(node(x, y, s, d));vis[x][y][s] = true;}
} int bfs(node s) {q.push(s);while(!q.empty()) {node u = q.front();q.pop();if(u.x == tx && u.y == ty) {return u.d;}// 共有5种方式向BFS的队列加入新的节点// 0, 1, 2, 3分别表示上右下左4个方向 // -1表示所有的方块顺时针方向旋转90度for(int i = -1; i < 4; i++) {expand(u, i);}}return -1;
}int main() {init();scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%s", G[i] + 1);}scanf("%d%d%d%d", &sx, &sy, &tx, &ty);vis[sx][sy][0] = true;printf("%d\n", bfs(node(sx, sy, 0, 0)));return 0;
}

(其它题目略)

这篇关于【解题报告】Codeforces Round #354 (Div. 2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924781

相关文章

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

Python:豆瓣电影商业数据分析-爬取全数据【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】

**爬取豆瓣电影信息,分析近年电影行业的发展情况** 本文是完整的数据分析展现,代码有完整版,包含豆瓣电影爬取的具体方式【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】   最近MBA在学习《商业数据分析》,大实训作业给了数据要进行数据分析,所以先拿豆瓣电影练练手,网络上爬取豆瓣电影TOP250较多,但对于豆瓣电影全数据的爬取教程很少,所以我自己做一版。 目

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

CSS实现DIV三角形

本文内容收集来自网络 #triangle-up {width: 0;height: 0;border-left: 50px solid transparent;border-right: 50px solid transparent;border-bottom: 100px solid red;} #triangle-down {width: 0;height: 0;bor