2021年度训练联盟热身训练赛第四场. C & K
C. Game Map
- 题意:给定n个点,有m条边,选择一条路径,保证第i个点的边大于第(i - 1)个点的边的数量,求该图最长的路径。
- 思路:dfs + 记忆化搜索(时间复杂度:O(N))
- 解析:
- 终止条件:if(cnt[x]) return cnt[x]; cnt[x]在搜索过程中都会递归的记录下从第x个结点出发的最长路径长度
- 搜索条件:if(d[v] > d[x]) cnt[x] = max(cnt[x], dfs(v) + 1);
假如x相邻结点v的度大于它的度,那么则可以进行搜索,加1的原因是加上x这个结点会与v有一条邻边,所以此时可看作是已经记录x -> v的路径
- 代码:
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e5 + 5;
vector<int> g[N];
int d[N], cnt[N];
int res = 0;
int n, m;
int dfs(int x)
{
if(cnt[x])
return cnt[x];
cnt[x] = 1;
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if(d[v] > d[x])
cnt[x] = max(cnt[x], dfs(v) + 1);
}
return cnt[x];
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
d[u] ++, d[v] ++;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 0; i < n ; i++)
res = max(res, dfs(i));
cout << res << endl;
return 0;
}
K. Untangling Chain
-
题意:起初从任意点出发,需要执行n步,每次步骤会有两个值,分别是这点所延长成线段的长度(可理解成一个点移动到某个位置后中间的距离形成一条线段)、移动方向,其中“1”则向左走,“-1”向右走,“0”,是最后一步走的方向(四个方向都行),并且一开始假设头朝下,相当于这个点向左移动时,在电脑屏幕面前看却是向右移动,然后问每一步的长度为多少时线段不会交叉(初始方向不能改变)。
-
解析:实际上这类题的思想有点像贪吃蛇游戏,假如我们不想让蛇的尾巴进行交叉,那我们肯定是每一次近可能在最大边界(有蛇身体的部位)的情况再往前走多一步,然后控制方向可用:0:up, 1:right,2:down,3:left进行表示,每次的方向进行相加并对4求余即可(这个规律有点奇妙,暂时没搞清楚原因)
-
原理图(红色圆圈就代表每次最大边界):

-
代码:
#include<iostream>
using namespace std;
int n;
int main()
{
cin >> n;
int dir = 0, nowx = 0, nowy = 0;
int minx = 0, miny = 0, maxx = 0, maxy = 0; //边界
for(int i = 1; i <= n; i++)
{
int len;
cin >> len >> dir;
dir += (dir + 4) % 4; //0:up, 1:right,2:down,3:left
if(dir == 0)
{
len = maxx + 1 - nowx;
nowx += len;
maxx = max(nowx, maxx);
}
else if(dir == 1)
{
len = maxy + 1 - nowy;
nowy += len;
maxy = max(nowy, maxy);
}
else if(dir == 2)
{
len = nowx - (minx - 1);
nowx -= len;
minx = min(nowx, minx);
}
else if(dir == 3)
{
len = nowy - (miny - 1);
nowy -= len;
miny = min(nowy, miny);
}
cout << len << " ";
}
return 0;
}

浙公网安备 33010602011771号