河南省第十三届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