A题:Red and Black
题意:从起始点出发,遇到坑不走,问能够到达的点有多少个。
思路:板子题。DFS或者BFS都可以
DFS:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))
const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 30;
int n,m,sum;
char mapp[N][N];
int vis[N][N];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
bool check(int x,int y){
if(x<0||x>=n||y<0||y>=m||mapp[x][y]=='#'){
return false;
}
else return true;
}
void DFS(int x,int y){
if(!check(x,y)||vis[x][y]){
return ;
}
else{
sum++;
int fx,fy;
for(int i=0;i<4;i++){
vis[x][y] = true;
fx = x + dx[i];
fy = y + dy[i];
DFS(fx,fy);
}
}
}
int main(){
while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
clr(mapp);clr(vis);
sum = 0;
for(int i=0;i<n;i++){
scanf("%s",mapp[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mapp[i][j] == '@'){
//cout<<i<<" "<<j<<endl;
DFS(i,j);
break;
}
}
}
printf("%d\n",sum);
}
return 0;
}
BFS:
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
const int N = 30;
int n,m,sum;
char mapp[N][N];
bool vis[N][N];
int dir[2][4] = { {1,-1,0,0}, {0,0,1,-1} };
bool check(int x,int y){
if(mapp[x][y]=='#'||x<0||x>=n||y<0||y>=m)
return false;
else return true;
}
struct node{
int x,y;
};
queue<node>Q;
void BFS(int x,int y){
node o;
o.x = x;
o.y = y;
Q.push(o);
vis[x][y] = true;
while(!Q.empty()){
sum ++;
o = Q.front();
Q.pop();
for(int i=0;i<4;i++){
int tx = o.x + dir[0][i];
int ty = o.y + dir[1][i];
if(check(tx,ty)&&!vis[tx][ty]){
node w ;
w.x = tx;w.y = ty;
Q.push(w);
vis[tx][ty] = true;
}
}
}
}
int main(){
while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
clr(mapp);clr(vis);
sum = 0;
while(!Q.empty()) Q.pop();
for(int i=0;i<n;i++){
scanf("%s",mapp[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mapp[i][j]=='@'){
BFS(i,j);
break;
}
}
}
cout<<sum<<endl;
}
return 0;
}
——————————————————————————————————————————————————————
B题:Tempter of the Bone
题意:问小狗是否能在第T分钟的时候恰好到达出口离开迷宫。
思路:本来想着用BFS,后来想想BFS求出的结果是最短路,但是在这道题里,最短路不一定就是T时间,所以BFS不可用,应 该用DFS顺便记录时间。
正解:DFS + 剪枝
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))
const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 55;
int n,m,T,dis;
int tx ,ty,sx,sy;
char mp[N][N];
bool vis[N][N],flag;
int dir[2][4]={ {1,-1,0,0},{0,0,1,-1} };
bool check(int x,int y){
if(x>=0&&x<n&&y>=0&&y<m) return true;
else return false;
}
void DFS(int x,int y,int t){
vis[x][y] = 1;
if(mp[x][y]=='D'&&t==T){
flag = 1;return;
}
//奇偶剪枝
int temp = T - t - (abs(x-tx)+abs(y-ty));
if(temp<0||(temp&1)) return ;
for(int i=0;i<4;i++){
int dx = x+dir[0][i];
int dy = y+dir[1][i];
if(check(dx,dy)&&!vis[dx][dy]&&mp[dx][dy]!='X'){
DFS(dx,dy,t+1);
if(flag) return ;
//回溯
vis[dx][dy] = false;
}
}
}
int main(){
while(scanf("%d%d%d",&n,&m,&T)!=EOF&&(n||m||T)){
clr(vis);clr(mp);
flag = false;
dis = 0;
for(int i=0;i<n;i++){
scanf("%s",mp[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='D'){
tx = i;ty = j;
}
if(mp[i][j]=='S'){
sx = i;sy = j;
}
}
}
dis = abs(sx-tx)+abs(sy-ty);
DFS(sx,sy,0);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
——————————————————————————————————————————————————————
C题:Oil Deposits
思路:DFS的板子题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int n,m;
char s[110][110];
int mapp[110][110];
int xx[8]={-1,1,0,0,-1,-1,1,1};
int yy[8]={0,0,-1,1,-1,1,-1,1};
void dfs(int a,int b){
if(a<0||a>=n||b<0||b>=m||mapp[a][b]==0){
return ;
}
mapp[a][b]=0;
for(int i=0;i<8;i++){
int na=a+xx[i];
int nb=b+yy[i];
dfs(na,nb);
}
}
//0是* 1是@ 0 是墙 1是路
int main(){
while(~scanf("%d%d",&n,&m)&&(n!=0&&m!=0)){
memset(mapp,0,sizeof(mapp));
memset(s,0,sizeof(s));
getchar();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",&s[i][j]);
if(s[i][j]=='*')
mapp[i][j]=0;
else
mapp[i][j]=1;
}
getchar();
}
int ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mapp[i][j]==1){
dfs(i,j);
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
——————————————————————————————————————————————————————
D题:How Many Equations Can You Find
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char s[10000];
long long n,ans,len;
void dfs(int sum,int id) {
if(id==len) {
if(sum==n) {
ans++;
}
return ;
} //判断是否是最后一个数
long long temp=0;
for(int i=id;i<len;i++) {
temp=temp*10+(s[i]-'0');
dfs(sum+temp,i+1);
if(id!=0)
dfs(sum-temp,i+1);
}
}
int main() {
while(scanf("%s%lld",s,&n)!=EOF) {
ans=0;
len=strlen(s);
dfs(0,0);
printf("%lld\n",ans);
}
return 0;
}
——————————————————————————————————————————————————————
E题:Fox And Two Dots
题意:判断图中,相同颜色是否能成环。
思路:DFS + 标记
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))
const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 55;
int n,m,num,fx,fy;
bool vis[N][N];
char mp[N][N];
int flag = 0;
int dir[2][4] = { {1,-1,0,0} ,{0,0,1,-1} };
bool check(int x,int y){
if(x>=0&&x<n&&y>=0&&y<m)
return true;
else return false;
}
void DFS(int x,int y,int fx,int fy,char s){
vis[x][y] = true;
for(int i=0;i<4;i++){
int dx = x+dir[0][i];
int dy = y+dir[1][i];
if(check(dx,dy)&&mp[dx][dy]==s){
if(dx==fx&&dy==fy) continue;//如果是上一个点则跳过
else{
if(vis[dx][dy]){//如果这个点之前被标记过,说明成环了
flag = 1;
return;
}
vis[dx][dy] = true;
DFS(dx,dy,x,y,s);
}
}
}
}
int main(){
cin>>n>>m;
clr(mp);clr(vis);
flag = 0;
for(int i=0;i<n;i++){
scanf("%s",mp[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(!vis[i][j]){
DFS(i,j,-1,-1,mp[i][j]);
if(flag == 1){
cout<<"Yes"<<endl;
return 0;
}
}
}
}
if(!flag)
cout<<"No"<<endl;
return 0;
}
——————————————————————————————————————————————————————
F题:Lakes in Berland
思路:用两个数组s[][],mapp[][]。s数组用来跑dfs并且记录湖泊数目与其面积,然后将数据传入结构体。但是跑完dfs之后,s数组就已经被填充完了,不能按照题目要求输出。所以用到了第二个mapp[][]数组,在按照题目要求填充湖泊(跑dfs1)之后,就可以按照顺序输出了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,k;
int xx[4]={-1,1,0,0};
int yy[4]={0,0,-1,1};
char s[110][110];
char mapp[110][110];
int ans=0;
struct node{
int x;
int y;// x,y 分别储存相应的横纵坐标
int num; // num储存有多少个湖泊块
}p[3000];//要大于2500,因为这个WA了一遍。
bool cmp(node a,node b){
return a.num < b.num;
}//按 从小到大的顺序排序。
void dfs(int a,int b){
if(a<0||a>=n||b<0||b>=m||s[a][b]=='*')
return ;
p[ans].num++;//记录湖泊的大小
s[a][b]='*';
for(int i=0;i<4;i++){
int na=a+xx[i];
int nb=b+yy[i];
dfs(na,nb);
}
}//这个用于s[][]跑dfs,顺便记录一下每个湖泊的位置和大小。(同一个湖泊只记录了一次)
void dfs2(int a,int b){
if(a<0||a>=n||b<0||b>=m||s[a][b]=='*')
return ;
s[a][b]='*';
for(int i=0;i<4;i++){
int na=a+xx[i];
int nb=b+yy[i];
dfs(na,nb);
}
}//这个dfs 用于填充海洋
void dfs1(int a,int b){
if(a<0||a>=n||b<0||b>=m||mapp[a][b]=='*')
return ;
mapp[a][b]='*';
for(int i=0;i<4;i++){
int na=a+xx[i];
int nb=b+yy[i];
dfs1(na,nb);
}
}//这个dfs 用于最后mapp[][] 按照已经给出的坐标开始填充湖泊
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
ans=0;
getchar();//消回车
memset(s,0,sizeof(s));
memset(mapp,0,sizeof(mapp));//数组清零
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",&s[i][j]);
mapp[i][j]=s[i][j];
}
getchar();//消回车
}
int i,j;//开始填充海洋
j=0;
for(i=0;i<n;i++)
if(s[i][j]=='.')
dfs2(i,j);
j=m-1;
for(i=0;i<n;i++)
if(s[i][j]=='.')
dfs2(i,j);
i=0;
for(j=0;j<m;j++)
if(s[i][j]=='.')
dfs2(i,j);
i=n-1;
for(j=0;j<m;j++)
if(s[i][j]=='.')
dfs2(i,j);
//填充海洋结束
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]=='.'){
p[ans].x=i;
p[ans].y=j;//记录湖泊的坐标
p[ans].num=0; //记录湖泊大小
dfs(i,j);//用s[][]跑dfs
ans++;//记录湖泊的个数
}
}
}
// printf("%d!!!\n",ans);
int sum=0;
sort(p,p+ans,cmp);//按照湖泊从小到大排序
for(int i=0;i<ans-k;i++){
dfs1(p[i].x,p[i].y);
sum+=p[i].num;
}
printf("%d\n",sum);//输出需要填充的湖泊的总面积
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%c",mapp[i][j]);
}//输出填充后的湖泊
printf("\n");
}
}
return 0;
}
——————————————————————————————————————————————————————
G题:棋盘问题
#include<cstdio>
#include<cstring>
int n,k;
char mapp[20][20];
bool vis[20];
int ans=0;
void dfs(int x,int cur){
if(cur==k)//完全填入一次加1
ans++;
for(int k=x;k<n;k++)//选择填入第几行的棋盘
{
for(int i=0;i<n;i++)//看哪一个是棋盘
{
if(mapp[k][i]=='#' && vis[i]==false)//回溯
{
vis[i]=true;
dfs(k+1,cur+1);
vis[i]=false;
}
}
}
}
int main(){
while(scanf("%d%d",&n,&k)!=EOF&&n!=-1&&k!=-1){
ans=0;
memset(vis,false,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%s",mapp[i]);
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}
——————————————————————————————————————————————————————
H题:The Game
别说了兄弟, 这题是真**恶心。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))
const int MAXN = 1e6+10;
const int INF = 0x3f3f3f3f;
const int N = 101;
int n,m,ans,cnt;
int x1,y2,x2;
int y1;
char mp[N][N];
bool vis[N][N];
int minn = MAXN;
int dir[2][4] = { {1,-1,0,0} , {0,0,1,-1} };
struct node{
int x,y,step;
};
bool check(int x,int y){
if(x>=0&&x<=n+1&&y>=0&&y<=m+1)
return true;
else return false;
}
void BFS(){
memset(vis,false,sizeof(vis));
node u,v;
queue<node>Q;
u.x = x1;u.y = y1;u.step = 0;
vis[u.x][u.y] = true;
Q.push(u);
while(!Q.empty()){
u = Q.front();
Q.pop();
if(u.x == x2&&u.y == y2){
minn = min(u.step,minn);
}
for(int i=0;i<4;i++){
v.x = u.x+dir[0][i];
v.y = u.y+dir[1][i];
while(check(v.x,v.y)&&!vis[v.x][v.y]&&(mp[v.x][v.y]==' '||(v.x==x2&&v.y==y2))){
vis[v.x][v.y] = true;
v.step = u.step + 1;
Q.push(v);
v.x += dir[0][i];
v.y += dir[1][i];
}
}
}
}
int main(){
int num = 1;
while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
clr(vis);
for(int i=0;i<=n+1;i++){
for(int j=0;j<=m+1;j++){
mp[i][j] = ' ';
}
}
getchar();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%c",&mp[i][j]);
}
getchar();
}
cout<<"Board #"<<num++<<':'<<endl;
cnt = 1;
while(scanf("%d%d%d%d",&y1,&x1,&y2,&x2)&&(y1||y2||x1||x2)){
minn = INF ;
cout<<"Pair "<<cnt++<<": ";
BFS();
if(minn==INF) cout<<"impossible.\n";
else cout<<minn<<" segments.\n";
}
cout<<endl;
}
return 0;
}
/*
5 4
XXXXX
X X
XXX X
XXX
2 3 5 3
1 3 4 4
2 3 3 4
0 0 0 0
*/
——————————————————————————————————————————————————————
I题:放苹果
#include<bits/stdc++.h>
using namespace std;
int DFS(int m,int n) {
if(m == 0 || n == 1)
return 1;
else if(n > m)
return DFS(m, m);
else
return DFS(m - n, n) + DFS(m, n - 1);
}
int main(void) {
int t, m, n;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &m, &n);
printf("%d\n", DFS(m, n));
}
return 0;
}
——————————————————————————————————————————————————————
K题:迷宫问题
思路:BFS+记录路径
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAX = 1e6+10;
const int INF = 0x3fffffff;
int way[15][15];
int mapp[15][15];
int vis[15][15];
struct node{
int x,y;
}p[210];
int dir[4][2]={0,1,1,0,-1,0,0,-1};
void BFS(int x,int y){
queue <node> q;
memset(vis,0,sizeof(vis));
memset(way,0,sizeof(way));
node cnt;
cnt.x=x;
cnt.y=y;
way[x][y]=0;//标记下起点的步数为0
q.push(cnt);//把起点入队列
vis[x][y]=1;//标记起点已经来过了
while(!q.empty()){
node ts = q.front();
q.pop();
if(ts.x==5&&ts.y==5) return;//如果已经找到右下角点则跳出
for(int i=0;i<4;i++){
int x1 = ts.x+dir[i][0];
int y1 = ts.y+dir[i][1];
if(!vis[x1][y1]&&mapp[x1][y1]==0&&x1>=1&&x1<=5&&y1>=1&&y1<=5){
//如果该位置不是墙,且之前没有走过
vis[x1][y1]=1;//标记走过
way[x1][y1]=way[ts.x][ts.y]+1;//标记一下步数
node temp;
temp.x=x1;
temp.y=y1;
q.push(temp);// 把新到的点入队列
}
}
}
}
void print(node a,node b){
if(a.x==b.x&&a.y==b.y) return ;//如果走到了右下点则结束
for(int i=0;i<4;i++){
int x1 = b.x+dir[i][0];
int y1 = b.y+dir[i][1];
if((way[b.x][b.y]==way[x1][y1]+1)&&vis[x1][y1]){
node temp;
temp.x=x1;
temp.y=y1;
print(a,temp);
printf("(%d, %d)\n",temp.x-1,temp.y-1);
}
}
return ;
}
int main(){
memset(mapp,0,sizeof(mapp));
memset(p,0,sizeof(p));
for(int i=1;i<6;i++){
for(int j=1;j<6;j++){
scanf("%d",&mapp[i][j]);
}
}
BFS(1,1);
node pre;
node last;
pre.x=1;pre.y=1;
last.x=5;last.y=5;
print(pre,last);
printf("(4, 4)\n");
return 0;
}