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;
}

浙公网安备 33010602011771号