2021牛客暑期多校训练营2(补题) 部分题解

题目链接:点这里

C.Draw Grids

  • 题意
    给定一个 n × m n\times m n×m的点阵,两人轮流进行操作:每次在点阵中选出两个未连接的相邻的点进行连线,规定不能连出封闭图形。当操作者不能进行操作时则输。

  • 解题思路
    可以意识到不围成封闭图形的线段总数量等于点的总数-1,不妨设不围成封闭图形的线段总数量为n,则有:
    n % 2 = 1 n\%2 = 1 n%2=1时,先手赢,否则后手赢。故此题易解。

#include<bits/stdc++.h>

using namespace std;

int n,m;
int main(){
    cin >> n >> m;
    if((n * m - 1) & 1){
        cout << "YES" << endl;
    }
    else{
        cout << "NO" << endl;
    }
    return 0;
}

D.Er Ba Game

  • 解题思路
    按题意模拟即可。

  • AC代码

#include<bits/stdc++.h>

using namespace std;

int t,a1,b1,a2,b2;
int main(){
    cin >> t;
    while(t -- ){
        cin >> a1 >> b1 >> a2 >> b2;
        if(a1 > b1)swap(a1,b1);
        if(a2 > b2)swap(a2,b2);
        if((a1 == 2 && b1 == 8) || (a2 == 2 && b2 == 8)){
            if((a1 == 2 && b1 == 8) && (a2 == 2 && b2 == 8)){
                cout << "tie" << endl;
            }
            else if(a1 == 2 && b1 == 8){
                cout << "first" << endl;
            }
            else{
                cout << "second" << endl;
            }
        }
        else if(a1 == b1 || a2 == b2){
            if(a1 == b1 && a2 == b2){
                if(a1 > a2){
                    cout << "first" << endl;
                }
                else if(a1 == a2){
                    cout << "tie" << endl;
                }
                else{
                    cout << "second" << endl;
                }
            }
            else if(a1 == b1){
                cout << "first" << endl;
            }
            else{
                cout << "second" << endl;
            }
        }
        else{
            int temp1 = (a1 + b1) % 10,temp2 = (a2 + b2) % 10;
            if(temp1 > temp2){
                cout << "first" << endl;
            }
            else if(temp1 < temp2){
                cout << "second" << endl;
            }
            else{
                if(b1 > b2){
                    cout << "first" << endl;
                }
                else if(b1 == b2){
                    cout << "tie" << endl;
                }
                else{
                    cout << "second" << endl;
                }
            }
        }
    }
    return 0;
}

I.Penguins

  • 题意
    给出两个地图,其中有两只企鹅一只在 ( 20 , 20 ) (20,20) (20,20),要到 ( 20 , 1 ) (20,1) (20,1)一只在 ( 20 , 1 ) (20,1) (20,1),要到 ( 1 , 1 ) (1,1) (1,1)。注意企鹅的动作是镜像同步的。求最小路径。

  • 解题思路
    相当于 b f s bfs bfs裸题,我们只需要控制一个地图上的企鹅即可,注意坐标变化以及状态点的定义。找到最短路径后,通过路径字符串来得到地图即可。

  • AC代码

/**
  *@filename:I
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-20 15:33
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 20 + 5;
const int P = 1e9+7;


char g1[N][N],g2[N][N];
string go[] = {"D","L","R","U"};
struct node{
    int x1,y1,x2,y2;
    string s;
};
bool vis[21][21][21][21];
void change(string s){
    //按照路径更改地图。
    char op = 'A';
    node head,temp;
    head.x1 = 20, head.y1 = 20, head.x2 = 20, head.y2 = 1;
    g1[20][20] = 'A',g2[20][1] = 'A';
    for(int i = 0; i < s.size(); ++ i){
        temp = head;
        if(s[i] == 'D'){
            temp.x1 += 1;
            temp.x2 += 1;
        }
        else if(s[i] == 'U'){
            temp.x1 -= 1;
            temp.x2 -= 1;
        }
        else if(s[i] == 'L'){
            temp.y1 -= 1;
            temp.y2 += 1;
        }
        else{
            temp.y1 += 1;
            temp.y2 -= 1;
        }
        if(temp.x1 < 1 || temp.y1 < 1 || temp.y1 > 20 || temp.x1 > 20 || g1[temp.x1][temp.y1] == '#'){
            temp.x1 = head.x1,temp.y1 = head.y1;
        } 
        if(temp.x2 < 1 || temp.y2 < 1 || temp.y2 > 20 || temp.x2 > 20 || g2[temp.x2][temp.y2] == '#'){
            temp.x2 = head.x2,temp.y2 = head.y2;
        }
        if(g1[temp.x1][temp.y1] != '#'){
            g1[temp.x1][temp.y1] = 'A';
        } 
        if(g2[temp.x2][temp.y2] != '#'){
            g2[temp.x2][temp.y2] = 'A';
        }
        head = temp;
    }
}
void solve(){
    node head,temp;
    queue<node> q;
    //起始点左企鹅在
    head.x1 = 20, head.y1 = 20, head.x2 = 20, head.y2 = 1;
    vis[20][20][20][1] = 1;
    head.s = "";
    q.push(head); 
    while(!q.empty()){
        head = q.front();
        q.pop();
        //判断是否到了该点。
        if(head.x1 == 1 && head.y1 == 20 && head.x2 == 1 && head.y2 == 1){
            cout << head.s.size() << endl;
            cout << head.s << endl;
            change(head.s);
            for(int i = 1; i <= 20; ++ i){
                cout << g1[i] + 1 << " " << g2[i] + 1 << endl;
            }
            break;
        }
        // cout << head.s << endl;
        for(int i = 0; i < 4; ++ i){
            temp = head;
            temp.s += go[i];
            if(go[i] == "D"){
                temp.x1 += 1;
                temp.x2 += 1;
            }
            else if(go[i] == "U"){
                temp.x1 -= 1;
                temp.x2 -= 1;
            }
            else if(go[i] == "L"){
                temp.y1 -= 1;
                temp.y2 += 1;
            }
            else{
                temp.y1 += 1;
                temp.y2 -= 1;
            }
            if((temp.x1 < 1 || temp.y1 < 1 || temp.x1 > 20 || temp.y1 > 20) && (temp.x2 < 1 || temp.y2 < 1 || temp.x2 > 20 || temp.y2 > 20))continue;
            if(temp.x1 >= 1 && temp.y1 >= 1 && temp.x1 <= 20 && temp.y1 <= 20 && temp.x2 >= 1 && temp.y2 >= 1 && temp.x2 <= 20 && temp.y2 <= 20
            &&g1[temp.x1][temp.y1] == '#' && g2[temp.x2][temp.y2] == '#')continue;
            if(temp.x1 < 1 || temp.y1 < 1 || temp.y1 > 20 || temp.x1 > 20 || g1[temp.x1][temp.y1] == '#'){
                temp.x1 = head.x1,temp.y1 = head.y1;
            } 
            if(temp.x2 < 1 || temp.y2 < 1 || temp.y2 > 20 || temp.x2 > 20 || g2[temp.x2][temp.y2] == '#'){
                temp.x2 = head.x2,temp.y2 = head.y2;
            } 
            if(vis[temp.x1][temp.y1][temp.x2][temp.y2])continue;
            vis[temp.x1][temp.y1][temp.x2][temp.y2] = true;
            q.push(temp);
        }
    }
}
int main(){
    for(int i = 1; i <= 20; ++ i){
        cin >> g1[i] + 1 >> g2[i] + 1;
    }
    solve();
    return 0;
}

K.Stack

  • 题意
    已知若干时刻的单调栈大小,构造一个合法的序列。

  • 解题思路
    首先,我们要清楚一点,单调栈的大小在某一时刻变化中要么不变要么增加。所以如果给出了一些若干时刻的单调栈的大小,我们就可以假设未知时刻的单调栈大小比前一时刻多 1 1 1即可。 假定这个就是 b b b数组,这个我们总能找到合法解,因为大小的变化是符合规定的,我们从尾部开始回归整个过程,如果此时刻单调栈大小比 b b b要小,我们就将元素入队。同理,栈顶为最后一个放入的元素,那么这个 a a a的值即为栈顶元素。据此得解。

  • AC代码

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;
int n,k,a[N],b[N];
int main(){
    cin >> n >> k;
    int p,x;
    bool flag = false;
    for(int i = 1; i <= k; ++ i){
        cin >> p >> x;
        b[p] = x;
        if(p < x)flag = true;
    }
    if(flag){
        cout << - 1 << endl;
    }
    else{
        for(int i = 1; i <= n; ++ i){
            if(!b[i])b[i] = b[i - 1] + 1;
        }
        stack<int> s;
        int temp = 0;
        for(int i = n; i >= 1; -- i){
            while(s.size() < b[i]){
                //说明当前栈的大小小于当前状态的大小。
                s.push(++ temp);
            }
            a[i] = s.top();//栈顶为最后一个放入的元素,自然为a[i]。
            s.pop();//到前一个状态栈顶元素并没有放入,不存在了。
        }
        for(int i = 1; i <= n; ++ i){
            cout << a[i] << " ";
        }
        cout << endl;
    }
    return 0;
}
posted @ 2022-03-26 16:48  unique_pursuit  阅读(10)  评论(0)    收藏  举报