CF1948C Arrow Path
做法一:记忆化搜索
注意到向左箭头没有用,当前点能到的充要条件是左边相邻点是右箭头,于是考虑左边相邻点可以从哪些点转移得到,由此记忆化搜索,时间复杂度 \(O(n)\)。
解释一下 \((2, n)\) 为什么不能由上方的 \((1,n)\) 走一步得到:但凡草稿上模拟一下过程就知道 \((1, n)\) 不能作为一次完整操作的终点,所以这个做法是对的。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 3e5;
int f[3][N], vis[3][N];
int n;
string s[3];
int solve(int x, int y){
// printf("(%d %d) ->\t", x, y);
if(y < 1) return 0;
if(vis[x][y] == 1) return f[x][y];
if(x == 1){
if(y > 1 && s[x][y - 1] == '>'){
f[x][y] = solve(x + 1, y - 1) | solve(x, y - 2);
}
}
else{
if(y > 1 && s[x][y - 1] == '>'){
f[x][y] = solve(x - 1, y - 1) | solve(x, y - 2);
}
}
vis[x][y] = 1;
return f[x][y];
}
void Main(){
cin >> n;
cin >> s[1] >> s[2];
s[1] = " " + s[1];
s[2] = " " + s[2];
F(i, 1, 2){
F(j, 1, n){
f[i][j] = 0;
vis[i][j] = 0;
}
}
f[1][1] = 1;
vis[1][1] = 1;
solve(2, n);
if(f[2][n] == 1){
cout << "YES\n";
}
else{
cout << "NO\n";
}
return ;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while(T --) Main();
return fflush(0), 0;
}
做法二:考虑转移本质
用 / 表示能作为中转点的点,发现是这样分布的:(#表示起点或终点)
# / # / # / #
/ # / # / # /
很好理解,因为每次移动的曼哈顿距离是偶数。
所以问题转化成是否存在一处位置不能前进。等价于是否有两个相邻的 < 。注意有两种情况:
# / # < # # < # / #
/ # < # / / # < # /
直接for就可以了。时间复杂度同样 \(O(n)\),空间复杂度更小。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 3e5;
int n;
string s[3];
int f[3][N];
void Main(){
cin >> n;
cin >> s[1] >> s[2];
s[1] = " " + s[1];
s[2] = " " + s[2];
int flag = 1;
for(int i = 2; i <= n; i += 2){
if(s[1][i] == '<' && s[2][i - 1] == '<'){
flag = 0;
break;
}
if(s[1][i] == '<' && s[2][i + 1] == '<'){
flag = 0;
break;
}
}
if(flag == 0){
cout << "NO\n";
}
else{
cout << "YES\n";
}
return ;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while(T --) Main();
return fflush(0), 0;
}
一个语法上的警示,这样写是错的:
cin >> s[1] >> s[2];
F(i, 1, 2){
G(j, n, 1){
s[i][j] = s[i][j - 1];
}
}
C++20及以后删除了 cin >> (s + 1) 的写法。

浙公网安备 33010602011771号