如果您不会单源最短路径,出门右拐搜索。
本刷题记会随时更新。啊你们不要说我找的都是水题啊!
Codeforces Beta Round #3 C.Tic-tac-toe
翻译
一个 \(3*3\) 棋盘,要你判断 \(A,B\) 哪个选手赢了,或者该谁下了,或者平局,或者棋盘不符合规则。
思路
水题,暴力可做,但是我们可以搜索出所有的情况,保存在一个 map
里,然后对于输出直接查找即可。
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<int(n);i++)
using namespace std;
string grid=".........";
map<string,string>ans;
int wins(char p)
{
rep(i,3) if(grid[i*3]==p&&grid[i*3+1]==p&&grid[i*3+2]==p)
return true;
rep(i,3) if(grid[i]==p&&grid[i+3]==p&&grid[i+6]==p)
return true;
if(grid[0]==p&&grid[4]==p&&grid[8]==p)
return true;
if(grid[2]==p&&grid[4]==p&&grid[6]==p)
return true;
return false;
}
void search(int t)
{
if(wins('X'))
{
ans[grid]="the first player won";
return;
}
else if(wins('0'))
{
ans[grid]="the second player won";
return;
}
else if(t==9)
{
ans[grid]="draw";
return;
};
if(t%2==0)
ans[grid]="first";
else
ans[grid]="second";
rep(i,9) if(grid[i]=='.')
{
grid[i]=t%2?'0':'X';
search(t+1);
grid[i]='.';
}
}
int main()
{
search(0);
string s,t;
rep(i,3)
{
cin>>t;
s+=t;
}
if(ans.find(s)==ans.end())
cout<<"illegal"<<endl;
else
cout<<ans[s]<<endl;
return 0;
}
Codeforces Beta Round #85 (Div. 1 Only) C Petya and Spiders
翻译
给出一个\(n×m\)的网格,每个网格里有一只蜘蛛,每只蜘蛛一秒都可以向四个方向跳一格,不可以跳出网格(当然它也可以选择不跳)。问一秒之后(每只蜘蛛都行动至多一次)网格上有至多多少个位置没有蜘蛛。
思路
找到一个有蜘蛛的点,把这个蜘蛛能走的位置枚举
枚举到一个位置看看能不能把它旁边的蜘蛛移动过来
Code
/*
找到一个有蜘蛛的点,把这个蜘蛛能走的位置枚举
枚举到一个位置看看能不能把它旁边的蜘蛛移动过来
*/
#include<bits/stdc++.h>
using namespace std;
int neigh[5][2]= {{0,0},{1,0},{0,1},{-1,0},{0,-1}}; ///方向数组
/**
0 0 0,1//不动
1,0 0,1//x+1往右走一步 纵坐标不动
2,0 2,1//横坐标不动 往下走一步
3,0 3,1//往左走一步 纵坐标不动
4,0 4,1//横坐标不动 往上走一步
**/
int best,m,n;
int a[50][50];
void search(int x)
{
int i,j,k,b1,x1,y1,xx,yy,x2,y2;
vector< pair<int,int> > tmp;
b1=0;
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
if(a[i][j]==0)///如果有蜘蛛
{
b1=1;
break;
}
if(b1==1)
break;
}
if(b1==0)///如果可以做到全没有
{
best=x;
return ;
}
if(x+1>=best)///如果超过best,剪枝
return ;
xx=i;
yy=j;///第一个有蜘蛛的位置
for(k=0; k<5; k++)///k:五个方向
{
x2=xx+neigh[k][0];///尝试把这个蜘蛛上下左右走或不动
y2=yy+neigh[k][1];
if(x2>=0&&x2<m&&y2>=0&&y2<n) ///判断边界
{
tmp.clear();
for(i=0; i<5; i++)
{
x1=x2+neigh[i][0];
y1=y2+neigh[i][1];///再尝试每一个方向,这个蜘蛛周围还是否蜘蛛可以往这个点走
if(x1>=0&&x1<m&&y1>=0&&y1<n&&a[x1][y1]==0) ///判断边界+有蜘蛛
{
tmp.push_back(make_pair(x1,y1)); ///将x1下标,y1值添加到vector
a[x1][y1]=1;///标记无蜘蛛
}
}
search(x+1);///继续下一步
for(i=0; i<tmp.size(); i++)
a[tmp[i].first][tmp[i].second]=0;///标记去除
}
}
}
int main()
{
cin>>m>>n;
memset(a,0,sizeof(a));
best=m*n;
search(0);
cout<<m*n-best<<endl;
return 0;
}
Codeforces Beta Round #80 (Div. 1 Only) B Cthulhu
翻译
给你 \(n\) 个点 \(m\) 条边的无向图(无重边和自环),问你是否存在一个简单的环且环上的点都是某棵树的树根。
思路
一道有思维但是代码简的题,要是你没有想明白,这就是一道简单但是也算的上坑的题,代码可能要上百行。那么让我讲解简单的方法。
如果一个图里有一个环,那么他的顶点数\(=\)边数。
然后看一下联通,既然是联通,那么一个点能到达的点和总点数一定相等。
Code
#include<bits/stdc++.h>
using namespace std;
int n,m,i,x,y,z;
vector <int> g[101];
bool u[1001];
void dfs(int i)
{
u[i]=true; z++;
for(int j=0;j<g[i].size();j++)
if(!u[g[i][j]])
dfs(g[i][j]);
}
int main()
{
cin>>n>>m;
for(i=0;i<m;i++)
{
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
if(n!=m)
return cout<<"NO"<<endl,0;
dfs(1);
if(z==n)
cout<<"FHTAGN!"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
Codeforces Round #125 (Div. 1) B Jumping on Walls
翻译
一张\(n*2\)的图,\(X\)代表不可走,\(-\)代表可以走。一个忍者\((0,1)\)开始起跳,有三种跳的方法,向对面往上跳\(k\)步,向上或者向下跳一步,每跳一次,洪水就会往上涨一格,问这个忍者能否跳出这张图。
思路
深度优先搜索的水题,就是题意真难理解。本题只要标记走过了,就别打回来,否则一般会无限递归。我们判断是否走出悬崖的条件有:
换一条路走\(k\)步出去了
直接走一步出去了
不合法就是洪水淹了你,回溯。
Code
#include<bits/stdc++.h>
using namespace std;
char s[2][100005];
int vis[2][100005];
int n,k;
void dfs(int x,int y,int d)
{
vis[x][y]=true;
if(y+k>=n||y+1>=n)
{
puts("YES");
exit(0);
}
if(d>=y)
return ;
if(s[!x][y+k]=='-'&&!vis[!x][y+k])
dfs(!x,y+k,d+1);
if(s[x][y-1]=='-'&&!vis[x][y-1]&&y-1>=0)
dfs(x,y-1,d+1);
if(s[x][y+1]=='-'&&!vis[x][y+1])
dfs(x,y+1,d+1);
}
int main()
{
int i,j;
cin>>n>>k;
cin>>s[0]>>s[1];
dfs(0,0,-1);
puts("NO");
return 0;
}