AtCoder Beginner Contest 335

本文介绍了如何通过二维网格模拟贪吃蛇游戏中的移动,使用队列结构存储蛇的身体部位,并处理贪吃蛇指定方向的移动。另外,还讨论了如何在给定条件下构造无向图并计算不同颜色路径的最大数量。
摘要由CSDN通过智能技术生成

前面两道阅读理解直接跳过。

C - Loong Tracking

大意

二维网格,贪吃蛇,移动,进行q次操作,分两种:

  • 指定贪吃蛇下一步移动的方向
  • 指定i,输出贪吃蛇的第 i个部位的坐标。

思路

每移动一次,只有头部到了新的坐标,其他部分的坐标都变成前一个。

如果我们把每个部分的坐标按顺序放在一个队列里,队尾是头部坐标,队头是尾部坐标,每次移动相当于一次出队和一次入队。

但是std::queue不支持下标访问,所以用std::vector(出队可以不操作)。

问第i个部位坐标就从队尾倒着数即可。

代码

#include<iostream>
#include<vector>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
vector<pll> a;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    ll n, q;
    cin >> n >> q;
    for(int i = 0; i < n; i++) a.push_back(make_pair(n - i, 0));
    while(q--){
        ll t;
        cin >> t;
        if(t == 1){
            string dir;
            cin >> dir;
            pll last = a.back();
            if(dir == "R") last.first++;
            if(dir == "L") last.first--;
            if(dir == "D") last.second--;
            if(dir == "U") last.second++;
            a.push_back(last);
        }else{
            ll p; 
            cin >> p;
            cout << a[a.size() - p].first << " " << a[a.size() - p].second << endl;
        }
    }
    return 0;
}

D - Loong and Takahashi

大意

给定一个n\times n的二维网格,n奇数,给每个格子一个数字\in [1,n^2-1],要求每个数字仅使用一次,且相邻数字的格子相邻,且正中间的格子不能是数字,而是T

给出一种构造方法。

思路

螺旋构造即可。

每次一个螺旋回字构造就填充最外围的一圈,起点依次为(1,1)\to(2,2)\to(3,3) ,最后恰好到正中间,因此能恰好填满

代码

#include <iostream>
#include <vector>
using namespace std;

void fillin(int e, vector<int> position, int start, vector<vector<int>> &grid){
    for(int i = 0; i < e; i++) grid[position[0]][position[1]++] = start++;
    for(int i = 0; i < e; i++) grid[position[0]++][position[1]] = start++;

    for(int i = 0; i < e; i++) grid[position[0]][position[1]--] = start++;
    for(int i = 0; i < e; i++) grid[position[0]--][position[1]] = start++;

}

int main(){
    ios::sync_with_stdio(0);
    int N;
    cin >> N;

    vector<vector<int>> grid(N, vector<int>(N));
    vector<int> p = {0, 0};
    int count = 1;
    for(int i = N - 1; i > 0; i -= 2){
        fillin(i, p, count, grid);
        p[0]++;
        p[1]++;
        count += i * 4;
    }


    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(i == (N + 1) / 2 - 1 && j == (N + 1) / 2 - 1) cout << "T ";
            else cout << grid[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

E - Non-Decreasing Colorful Path

大意

给定一个n个点m条边的无向图,图上每个点都有其颜色。求所有经过点权单调不降1n的路径中,出现的不同颜色的个数最多是多少。

思路

对于a_u>a_v的情况下,该边一定是无效的,所以我们只往图中添加a_u\le a_v的边,注意这是一个无向图,所以需要判断正反两次

然后普通的dijkstra肯定是不行的,需要更改下面这些逻辑:

  • 对于优先队列:如果两者点权相同,那么优先选择从1到该点路径上不同颜色更多的,否则选择点权更小的。注意优先队列的优先级与cmp是反的
  • 对于dijkstra跑图过程:如果遍历到的点的点权大于现在这个点,答案数会加一。

代码

#include<iostream>
#include<queue>
using namespace std;
const int N = 2e5 + 9;
int n, m, a[N], dis[N];
vector<int> G[N];
struct Node{
	int id, cnt;
	Node(int x, int y): id(x), cnt(y) {};
	bool operator < (const Node q) const{
		return (a[id] == a[q.id]? cnt < q.cnt: a[id] > a[q.id]);
	}
};
void dijkstra(int st){
    priority_queue<Node> q;
	dis[st] = 1;
	q.push(Node(st, 1));
	while(q.size()){
		auto x = q.top();
		q.pop();
		for(int v: G[x.id]){
			if(dis[v] < dis[x.id] + (a[x.id] < a[v])){
				dis[v] = dis[x.id] + (a[x.id] < a[v]);
				q.push(Node(v, dis[v]));
			}
		}
	}
}

void add(int u, int v){
    if(a[u] <= a[v]) G[u].push_back(v);
	if(a[v] <= a[u]) G[v].push_back(u);
}
int main(){
    ios::sync_with_stdio(0);
	cin >> n >> m;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1, u, v; i <= m; i++){
		cin >> u >> v;
		add(u, v);
	}
	dijkstra(1);
	cout << dis[n] << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值