2021年度训练联盟热身训练赛第四场. C & K

C. Game Map

  • 题意:给定n个点,有m条边,选择一条路径,保证第i个点的边大于第(i - 1)个点的边的数量,求该图最长的路径。
  • 思路:dfs + 记忆化搜索(时间复杂度:O(N))
  • 解析:
    1. 终止条件:if(cnt[x]) return cnt[x]; cnt[x]在搜索过程中都会递归的记录下从第x个结点出发的最长路径长度
    2. 搜索条件: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;
}

posted @ 2021-03-29 21:30  ~K2MnO4  阅读(136)  评论(0)    收藏  举报