河南省第十三届ICPC大学生程序设计竞赛 部分题题解

Posted 辉小歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了河南省第十三届ICPC大学生程序设计竞赛 部分题题解相关的知识,希望对你有一定的参考价值。

比赛参加了,打的很垃圾。
霸爷说过:一个人要不是比别人大几个数量级,其实是很难比别人强的。
努力变强,到达巅峰。

A: 祝融传火

在这里插入图片描述
https://ac.nowcoder.com/acm/contest/17148/A
名字很厉害,题目讲的也很厉害,结果就是一个签到题。
暴力枚举,看4个顶点的数是不是相等即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
typedef long long int LL;
const int N=1e3+10;
int n,m; 
int a[N][N];
int main(void)
{ 
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		cin>>a[i][j];
	}
	int h,w; cin>>h>>w;
	bool flag=false;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			int x=i+h-1;
			int y=j+w-1;
			if(x>=n||y>=m) continue;
			if(a[i][j]==a[x][j]&&a[i][j]==a[i][y]&&a[i][j]==a[x][y])
			{
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	if(flag) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
	return 0;
} 

E: Dance with a stick

在这里插入图片描述
https://ac.nowcoder.com/acm/contest/17148/E
官方题解:
在这里插入图片描述
这道题居然是某一年的IMO的题,是一个大风车的问题。大风车证明视频讲解
答案上其实说的也是很清楚了就是说,我们总的数是奇数,这样选一个中点才可以正好的对半分,每次移动。
左右两边的点的数量是不变的。关键的问题在于方向向量如何确认。为何是(-1,1e9)。
以下是我的观点(不一定百分百正确):
在这里插入图片描述
当然这里的点的的数量太少了,那么如果点的数量太多的话,我们得这样。
在这里插入图片描述
那么题目给的范围是[-1e9,1e9] 那么斜率最小就是-1e9 即 y=-1e9x
当x=-1 即 y=1e9 。这就是题解给的答案。(题目说了结果是整数)
如果x=1 y=-1e9 可不可以呢? 答案是肯定的。
在这里插入图片描述

#include<cstdio>
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
vector< pair<int,int> > ve;
int main(void)
{
	int n; cin>>n;
	for(int i=0;i<n;i++)
	{
		int x,y; cin>>x>>y;
		ve.push_back({x,y});
	}
	sort(ve.begin(),ve.end());
	if(ve.size()%2==0) 
	{
		cout<<"No"<<endl;
		return 0;
	}
	cout<<"Yes"<<endl;
	int ansx=ve[n>>1].first,ansy=ve[n>>1].second;
	printf("%d %d %d %d\\n",ansx,ansy,-1,1e9);
    //printf("%d %d %d %d\\n",ansx,ansy,1,-1e9);
	return 0;
}

F: 图像识别

在这里插入图片描述
https://ac.nowcoder.com/acm/contest/17148/F
找原点,找目标点。
原点有以下几种情况:
即原点在四个角或者,中间处。
自己的垃圾做法:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
typedef long long int LL;
const int N=1e3+10;
char a[N][N];
int n,m;
int x,y;//目标 
int xx,yy;//原点 
int dfs(int x,int y)
{
	int dx[4]={-1,0,1,0};
	int dy[4]={0,1,0,-1};
	int sum=0;
	for(int i=0;i<4;i++)
	{
		int tempx=x+dx[i];
		int tempy=y+dy[i];
		if(tempx>=1&&tempx<=n&&tempy>=1&&tempy<=m&&a[tempx][tempy]=='*') sum++;
	}
	return sum;
}
int main(void)
{ 
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
			if(a[i][j]=='#')  x=i,y=j;
		}
	}
	bool flag=false;
	if(a[1][1]='*'&&a[1][2]=='*'&&a[2][1]=='*')  xx=1,yy=1,flag=true;//四个点
	if(a[1][m]='*'&&a[1][m-1]=='*'&&a[2][m]=='*')  xx=1,yy=m,flag=true;
	if(a[n][1]='*'&&a[n-1][1]=='*'&&a[n][2]=='*')  xx=n,yy=1,flag=true;
	if(a[n][m]='*'&&a[n][m-1]=='*'&&a[n-1][m]=='*')  xx=n,yy=m,flag=true;
	
	if(!flag)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(a[i][j]=='*')
				{
					int t=dfs(i,j);
					if(t>=3)
					{
						xx=i,yy=j;
						flag=true;
						break;
					}
				}
			}
			if(flag) break;
		}
	}
	cout<<y-yy<<" "<<xx-x<<endl;
	return 0;
} 

在这里插入图片描述
故优化为:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m,a,b,x,y;
    scanf("%d%d",&n,&m);
    char c;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>c;
            if(c=='#'){
                a=i;b=j;
            }
            if(j==1&&c=='*')y=i;
            if(i==1&&c=='*')x=j;
        }
    }
    printf("%d %d",b-x,y-a);
}

H: 焦糖布丁 【博弈论 nim】

![
https://ac.nowcoder.com/acm/contest/17148/H
不会写,可以看出是一个nim游戏,但是不会搞,线性基不会。
大佬代码:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=47917810

#include<bits/stdc++.h>
#define ll long long
using namespace std;
//深度为偶数的点对答案无影响,然后所有奇数点构成nim游戏
//由于对面先手,原问题转化为能否找到一组异或和为0的子序列
//用线性基糊弄,某个数不能插入说明找到了
ll a[65],b[65];
ll add(ll x)
{
    ll flag=0;
    for(ll i=60;i>=0;--i)//2^60>10^18
    {
        if(x&(1ll<<i))
        {
            if(b[i]) x^=b[i];
            else {b[i]=x;flag=1;break;}
        }
    }
    return flag;
}
int main()
{
    ll t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(ll i=1;i<=n;++i) cin>>a[i];
        ll flag=0;
        for(ll i=1;i<=n;++i)
        {
            if(!add(a[i])) {cout<<"Yes"<<endl;flag=1;break;}
        }
        if(!flag) cout<<"No"<<endl;
        for(ll i=0;i<=60;++i) b[i]=0;
    }
    return 0;
}

I: 七便士

在这里插入图片描述
https://ac.nowcoder.com/acm/contest/17148/I
爆搜即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
typedef long long int LL;
bool st[15];
bool flag=false;
int k=0;//统计共有几个空位,即可以进行几次放的操作
void dfs(int index)
{
	if(index==k)
	{
		int ans=0;
		for(int i=1;i<=8;i++)
		{
			if(st[i]) ans++;
		}
		if(ans==7) flag=true;//说明共放了7个
		return;
	}
	for(int i=1;i<=8;i++)
	{
		if(!st[i])//当前位是空
		{
			if(!st[(i+2)%8+1])//第一条线可以放
			{
				st[(i+2)%8+1]=true;
				dfs(index+1);
				st[(i+2)%8+1]=false;	
			}
			
			if(!st[(i+4)%8+1])//第二条线可以放
			{
				st[(i+4)%8+1]=true;
				dfs(index+1);
				st[(i+4)%8+1]=false;	
			}
		}
	}
}
int main(void)
{ 
	int t; cin>>t;
	while(t--)
	{
		char s[15]; cin>>s+1;
		memset(st,0,sizeof st);
		k=0;
		flag=false;
		for(int i=1;i<=8;i++)
		{
			if(s[i]=='1') st[i]=true;
			else k++;
		}
		dfs(1);
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
} 

J: 甜甜圈 【模拟TLE做法 正解不会】

在这里插入图片描述
https://ac.nowcoder.com/acm/contest/17148/J
正解是用线段树或树状数组等来完成加速,但是我没学,据说就是一个板子题。
在这里插入图片描述

#include<cstdio>
#include<iostream>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int n,m;
stack<int>s1,s2河南省第十三届ICPC大学生程序设计竞赛 G.Elo mountains

尺取法二分河南省第十三届ICPC大学生程序设计竞赛 C题

2021河南省第十三届ICPC大学生程序设计竞赛 A.祝融传火(暴力,签到)

河南省第十三届ICPC大学生程序设计竞赛重现赛感悟

河南省第十三届ICPC大学生程序设计竞赛重现赛感悟

j-甜甜圈(第十三届icpc河南省赛)