首页 > 其他分享 >AtCoder Beginner Contest(abc) 311

AtCoder Beginner Contest(abc) 311

时间:2023-10-31 09:24:15浏览次数:36  
标签:AtCoder abc int 311 long 坐标 tie dp define




B - Vacation Together

难度: ⭐

题目大意

给定n个人的工作计划, 'o'表示这天休息, 'x'表示工作; 请找出一段最长的所有人都休息的连续休息的天数;

解题思路

数据不大, 暴力即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e3 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m;
int f[N];
signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			char c;
			cin >> c;
			if (c == 'o') f[j]++;
		}
	}
	int res = 0, maxn = 0;
	for (int i = 1; i <= m; i++) {
		if (f[i] == n) res++;
		else {
			maxn = max(maxn, res);
			res = 0;
		}
	}
	maxn = max(maxn, res);
	cout << maxn;
	return 0;
}




C - Find it!

难度: ⭐⭐

题目大意

给定一个有向图, 不一定连通, 但是保证一定存在环, 请你找出任意一个环, 该环中没有重复的节点, 输出环中结点的数量和所有结点;

解题思路

用一个数组保存路径, dfs遍历所有点即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m;
vector<int> v[N];
vector<int> res;
int d[N];
bool st[N];
void find(int u) {
	if (st[u]) {
		int i = 0;
		while (res[i] != u) i++;
		cout << res.size() - i-1 << endl;
		for (; i < res.size()-1; i++) cout << res[i] << ' ';
		exit(0);
	}
	st[u] = true;
	for (int x : v[u]) {
		res.push_back(x);
		find(x);
		res.pop_back();
	}
}
signed main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int x;
		cin >> x;
		v[i].push_back(x);
	}
	for (int i = 1; i <= n; i++) {
		if (!st[i]) {
			res.push_back(i);
			find(i);
			res.pop_back();
		}
	}
	return 0;
}




D - Grid Ice Floor

难度: ⭐⭐⭐

题目大意

给定一个n*m的字符矩阵, 其中'.'表示这块是雪地, '#'表示是岩石; 该矩阵的最外圈都是岩石; 小莫的初识位置在(2,2)这个点; 小莫接下来可以选择上下左右四个方向, 确定好方向后就会一直沿着这个方向前进直到遇到岩石才会停下来再选择方向; 问小莫可以经过多少块雪地;

解题思路

这题dfs和bfs好像都可以, 但是bfs会更好写; 在理解题意后我们可以想到, 小莫可能以不同的方向经过同一块雪地, 所以在保存状态时我们要三个变量, 坐标x, y和方向d; 所以我们要对经过的地方打上两个标记, sw(是否经过某个坐标), st(以某个方向经过某个坐标); 再更新队列时, 如果还能按照原方向接着走, 就接着更新即可; 如果不行就遍历4个方向找可以走的方向, 只要下一个不越界, 并且以该方向没有经历过就可以放进队列中;

神秘代码

#include<bits/stdc++.h>
#include<unordered_map>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e3 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
char g[N][N];
bool sw[N][N];
bool st[N][N][5];
struct stu {
	int x, y, d;
};
int dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 };
void bfs(){
	queue<stu> q;
	for (int i = 0; i < 4; i++) {
		q.push({ 2,2,i });
		st[2][2][i] = 1;
	}
	while (q.size()) {
		auto t = q.front();
		if (!sw[t.x][t.y]) {
			res++;
			sw[t.x][t.y] = true;
		}		
		q.pop();
		int xf = t.x + dx[t.d], yf = t.y + dy[t.d], d = t.d;
		if (xf>=1&&xf<=n&&yf>=1&&yf<=m&&g[xf][yf] == '.') {
			if (st[xf][yf][d]) continue;
			q.push({ xf,yf,d });
			st[xf][yf][d] = 1;
		}
		else {
			for (int i = 0; i < 4; i++) {
				int x = t.x + dx[i], y = t.y + dy[i];
				if (x >= 1 && x <= n && y >= 1 && y <= m && g[x][y] == '.') {
					if (st[x][y][i]) continue;
					q.push({ x,y,i });
					st[x][y][i] = 1;
				}
			}
		}
	}
}
signed main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> g[i][j];
		}
	}
	bfs();
	cout << res;
	return 0;
}




E - Defect-free Squares

难度: ⭐⭐⭐

题目大意

在一张n*m的图中, 有k个坐标格子上有个洞; 请问有多少个正方形区域内没有洞; 只要两个方形区域的左上方坐标和右下方坐标和其他方形区域不同, 那么这两个方形区域就可以看作是不同的; 单独的一个格子也可以看作一个边长为1的方形区域;

解题思路

由题意我们可以想到先固定一个不是洞的坐标(x,y), 然后求出所有以该坐标为右下角坐标的方形区域个数; 并且我们发现只要存在以(x-1,y), (x-1,y-1), (x,y-1)这三个相邻位置坐标为右下角坐标的方形区域, 我们就可以用他们来推断以(x,y)为右下角坐标的方形区域中是否有洞; 只要三个坐标都存在边长为n的方形区域, 我们就可以(x,y)为右下角坐标且边长为(n+1)的方形区域中没有洞; 像这种存在相互关系的计数问题, 我们可以考虑用dp来做; 具体方式也很直接, 状态表示dp[i][j]表示以(i,j)为右下角的没有洞的方形区域个数; 状态计算就像刚才说的: dp[i][j] = min(dp[i - 1][j - 1], min(dp[i][j - 1], dp[i - 1][j])) + 1; 最后遍历所有坐标把dp[i][j]加起来即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
bool st[3010][3010];
int dp[3010][3010];
signed main(){
	IOS;
	int k;
	cin >> n >> m >> k;
	for (int i = 1; i <= k; i++) {
		int a, b;
		cin >> a >> b;
		st[a][b] = true;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (st[i][j]) continue;
			dp[i][j] = min(dp[i - 1][j - 1], min(dp[i][j - 1], dp[i - 1][j])) + 1;
		}
	}
	int res = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			res += dp[i][j];
		}
	}
	cout << res;
	return 0;
}




F - Yet Another Grid Task

难度: ⭐⭐⭐⭐

题目大意

给定一个由黑白色块表示的n*m的一个图; '.'表示白色, '#'表示黑色; 如果图中的所有黑色块都满足下面这个条件, 那么这个图就是合法的;
条件是: 设一个黑色块的坐标为(x,y): 如果坐标(x+1,y)存在, 那么这个坐标的色块必须是黑色; 如果坐标(x+1,y+1)存在, 那么这个坐标的色块也必须是黑色;
现在我们可以选择把任意数量的白色块染成黑色块, 请问我们可以把原图构造为多少种不同的合法的图;

解题思路

由题意得, 假设当前是一个合法图, 如果在第i列有一个自下而上高度为j的黑色块, 那么第i列从下往上一直到j都要是黑色块, 同时, 第i+1列必须要有一个高度为j-1的黑色块; 再继续分析, 还是第i列有一个高度为j的黑色块, 那么第i-1列的黑色块高度最高就是j+1, 如果再往上, 那么第i列高度为j的色块就不合法了; 发现有状态的转移, 所以可以考虑用dp来求解; 一开始我们先按题目要求把原图修改为最基础的合法图, 然后我们在这个图上进行修改; 状态表示: dp[i][j] 表示修改前i列, 并且第i列的黑色块高度最高为j时所有合法图的数量; 根据前面所提到的范围, 我们可以得到状态转移: dp[i][j] = dp[i][j] + dp[i - 1][k], 但是这样需要三重循环, 所以我们可以先从第i列的j-1行开始转移; 因为dp[i][j-1]已经包括了第i-1列高度一直到(j-1+1) = j的情况; 所以dp[i][j]只需要再补充一个到j+1的高度即可, 如果j+1>n了就再补充一个n即可; 所以新的转移方差就是dp[i][j] = dp[i][j-1] + dp[i - 1][min(n,j+1)];

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e3 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
char g[N][N];
int dp[N][N];
int bak[N];
signed main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> g[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (g[i][j] == '#'){
				g[i + 1][j] = g[i + 1][j + 1] = '#';
				bak[j] = max(bak[j], n - i + 1);
			}
		}
	}
	for (int i = 0; i <= n; i++) dp[0][i] = 1;

    // for (int i = 1; i <= m; i++) {
	// 	for (int j = bak[i]; j <= n; j++) {
	// 		for (int k = bak[i]; k <= min(n,j + 1); k++) {
	// 			(dp[i][j] += dp[i - 1][k]) %= mod;
	// 		}
	// 	}
	// }这是朴素版本, n的三次方

	for (int i = 1; i <= m; i++) {
		for (int j = bak[i]; j <= n; j++) {
			(dp[i][j] = dp[i][j-1] + dp[i - 1][min(n,j+1)]) %= mod;//前缀和优化
		}
	}
	cout << dp[m][n];
	return 0;
}

标签:AtCoder,abc,int,311,long,坐标,tie,dp,define
From: https://www.cnblogs.com/mostimali/p/17799508.html

相关文章

  • AtCoder Beginner Contest 321(ABC321)
    A.321-likeChecker直接模拟。CodeB.Cutoff直接暴力枚举\([0\sim100]\),每次把第\(n\)个数当作当前枚举的\(i\),然后看看条件是否满足。CodeC.321-likeSearcherDescription给你一个\(K\),求出\([1\simK]\)区间内有多少个321-likeNumber。321-likeNumber的......
  • Atcoder Beginner Contest 326 (ABC326)
    不知道为什么拖到现在,我是摆怪。A.2UP3DOWN模拟,略。B.326-likeNumbers模拟,略。C.Peak双指针板子。D.ABCPuzzle基础dfs。但是赛时不知道为什么觉得状态数不会很少,于是写了一个巨大复杂的状压。这里粗略算算有效状态数:仅考虑每行的限制,有\(\binom{3}{5}=10\)种选......
  • 题解 ABC326G【Unlock Achievement】
    题解ABC326G【UnlockAchievement】problem有\(n\)项属性,第\(j\)个属性的等级\(l_j\)初始为\(1\),每提升一级花费\(c_j\)的钱。又有\(m\)项成就,第\(i\)项成就要求对于所有\(1\leqj\leqn\),都要\(l_j\geqL_{i,j}\),如果满足所有要求,获得\(a_i\)的钱。求你最多......
  • 学年(2023-2024-1)学号(20231311)《计算机基础与程序设计》第5周学习总结
    2023-2024-120231311《计算机基础与程序设计》第5周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计第五周作业这个作业的目标下载Pep/9虚拟机,学习机器语言与汇编语言,算法与伪代码等......
  • 一个字符串 AbAbcBaB 这种 消除驼峰字段 AbA aBa 这种 只留下非驼峰比如刚才这个字符
    publicclassSolution{char[]c=s.toCharArray();intlen=c.length;if(len<=2){System.out.println(c[len]);}intj=-1;for(inti=0;i<len-2;i++){if(c[i]==c[i+2]&&c[i]!=c[i+1]){j=i+2;......
  • AT_abc_326
    好久没打abc了,久违的rated一场比赛,结果被D创飞了。\(9\)分钟把ABC题切掉,然后看D题,觉得是个简单的模拟,错了\(5\)次,直接把我人整懵了,一看题目字符a,b,c只出现一次,我以为是字符a,b,c至少出现一次,妈妈生的。E求期望,有个很显然的东西,就是\(ans=\sum_{i=1}^{n}a_i\t......
  • ABC326
    此前也没有写一整场比赛题解的习惯,那就从现在开始吧。D:简单的一道题,直接搜就行了。代码:#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;template<classT>boolchmax(T&a,constT&b){if(a<b){a=b;returntrue;}returnfalse;}template<c......
  • AtCoder Beginner Contest 326
    A-2UP3DOWN(abc326A)题目大意100楼层,一次可以上最多两层,或下最多三层。给定两楼层,问能否一次到达。解题思路比较大小,然后判断其差是是不是在\(2\)或\(3\)内即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){......
  • ABC326
    上次说我的写法low的人的AT号在这里!!(我又来提供low算法了。从D开始。T4我们把\(\text{A}\)看成\(1\),把\(\text{B}\)看成\(2\),把\(\text{C}\)看成\(3\)。那么就可以想到状压,然后把每一行和每一列的情况状态即可。#include<bits/stdc++.h>usingnamespacestd;......
  • AtCoder Beginner Contest 326 题解
    首先,\(\text{HappyBirthdaytome!}\)A-2UP3DOWN常规ABCA...//If,oneday,Ifinallymanagetomakemydreamsareality...//Iwonder,willyoustillbetherebymyside?#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false)#defineTI......