#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n,k;
char mp[10][10];
int book[10];
int ans;
void dfs(int num, int stp)
{
if (stp==k)
{
ans++;
return;
}
if (num==n)
return ;
for (int i = 0; i < n; i++)
{
if (!book[i] && mp[num][i]=='#')
{
book[i]=1;
dfs(num+1,stp+1);
book[i]=0;
}
}
dfs(num+1, stp);
return;
}
int main(void)
{
while (scanf("%d %d", &n, &k))
{
if (k==n&&n==-1)
break;
ans = 0;
memset(book,0,sizeof(book));
for (int i = 0; i < n; i++)
{
scanf(" %s", mp[i]);
}
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}
题意:有一个高L长R宽C的迷宫, 问从S走到E的步数,如果走不到就输出“Trapped!”。
思路:六个方向BFS。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct node{
int x, y, z;
int stp;
}M;
char mp[35][35][35];
int book[35][35][35];
int nxt[6][3] = {1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1};
int L, R, C;
void bfs(int sx, int sy, int sz)
{
M a,b;
queue q;
a.x = sx;
a.y = sy;
a.z = sz;
a.stp = 0;
q.push(a);
while (!q.empty())
{
a = q.front();
q.pop();
if (mp[a.x][a.y][a.z]=='E')
{
printf("Escaped in %d minute(s).\n", a.stp);
return;
}
for (int i = 0; i < 6; i++)
{
int nx = a.x+nxt[i][0];
int ny = a.y+nxt[i][1];
int nz = a.z+nxt[i][2];
if (nx<0||ny<0||nz<0 || nx>=L ||ny>=R||nz>=C)
continue;
if (!book[nx][ny][nz]&&mp[nx][ny][nz]!='#')
{
b.x = nx;
b.y = ny;
b.z = nz;
b.stp = a.stp+1;
q.push(b);
book[nx][ny][nz]=1;
}
}
}
printf("Trapped!\n");
}
int main(void)
{
while (scanf("%d %d %d", &L, &R, &C))
{
if (L+R+C==0)
break;
int sx,sy,sz;
memset(book,0,sizeof(book));
for (int i = 0; i < L; i++)
{
for (int j = 0; j < R; j++)
{
scanf(" %s", mp[i][j]);
for (int k = 0; k < C; k++)
{
if (mp[i][j][k]=='S')
{
sx=i;
sy=j;
sz=k;
book[sx][sy][sz]=1;
}
}
}
}
//printf("%d %d %d", sx, sy, sz);
bfs(sx,sy,sz);
}
return 0;
}
题意:给一个N一个K,问经过多少步(N++,N–,N*=2)后 N可以变成K。
思路:BFS三种情况,注意判断边界。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int book[100000+100];
typedef struct node{
int x,stp;
}P;
int main(void)
{
int n,k;
while (~scanf("%d %d", &n, &k))
{
memset(book,0,sizeof(book));
book[n]=1;
queueq;
P p;
p.x=n;
p.stp=0;
q.push(p);
while (!q.empty())
{
p = q.front();
q.pop();
if (p.x==k)
{
printf("%d\n", p.stp);
break;
}
P pp;
if ( p.x+1<=k && !book[p.x+1])
{
pp.x = p.x+1;
pp.stp = p.stp+1;
q.push(pp);
book[p.x+1]=1;
}
if (p.x-1>=0 && !book[p.x-1])
{
pp.x = p.x-1;
pp.stp = p.stp+1;
q.push(pp);
book[p.x-1]=1;
}
if (p.x<=50000 && !book[p.x*2])
{
pp.x = p.x*2;
pp.stp = p.stp+1;
q.push(pp);
book[p.x*2]=1;
}
}
}
return 0;
}
题意:给一个M*N的图,要求将图中的1全反转成0, 反转一个格子,会将本身及上下左右全部反转, 如果可以反转,则输出最小步数的反转的图,如果不能则输出“IMPOSSIBLE”。
思路:枚举第一行的所有情况
for (int i = 0; i < 1<
memset(book,0,sizeof(book));
for (int j = 0; j < N; j++)
book[0][N-j-1] = i>>j&1;
}
然后从第二行开始,如果i-1个是1,则当前位置必反转。直到循环结束,判断最后一行是不是全为0。并记录最小步数。
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using namespace std;
int M,N;
int mp[20][20];
int ans[20][20];
int book[20][20];
int nxt[5][2]={1,0,0,1,-1,0,0,-1,0,0};
int stp;
int check(int x, int y)
{
int p=mp[x][y];
for (int i = 0; i < 5; i++)
{
int nx = x + nxt[i][0];
int ny = y + nxt[i][1];
if (nx>=0&&nx=0&&nyreturn p&1;
}
int F()
{
for (int i = 1; i < M; i++)
for (int j = 0; j < N; j++)
if (check(i-1,j)!=0)
book[i][j]=1;
for (int i = 0; i < N; i++)
if (check(M-1,i)!=0)
return inf;
int num = 0;
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
num+=book[i][j];
return num;
}
void deal()
{
stp = inf;
for (int i = 0; i < 1<memset(book,0,sizeof(book));
for (int j = 0; j < N; j++)
book[0][N-j-1] = i>>j&1;
int num = F();
if (nummemcpy(ans,book,sizeof(ans));
stp = num;
}
}
if (stp == inf)
{
printf("IMPOSSIBLE\n");
}
else
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
printf("%d%c", ans[i][j], j==N-1?'\n':' ');
}
}
return;
}
int main(void)
{
while (~scanf("%d %d", &M, &N))
{
for(int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
scanf("%d", &mp[i][j]);
deal();
}
return 0;
}
题意:求能被n整除的只含0 1 的数字。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n,flag;
void dfs(unsigned __int64 t, int n, int k)
{
if (flag)
return;
if (t%n==0)
{
printf("%I64u\n", t);
flag=1;
return;
}
if (k>=19)
return;
dfs(t*10,n,k+1);
dfs(t*10+1,n,k+1);
}
int main(void)
{
while (scanf("%d", &n))
{
if (n==0)
break;
flag=0;
dfs(1,n,0);
}
return 0;
}
题意:将M变换成N,要求每次只能变一位,并且只能变成素数。
思路:对于每位进行bfs。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct node{
int x;
int stp;
}P;
int book[10000];
int change(int x, int a, int b)
{
int num = 0;
for (int t = 1000; t > 0; t/=10)
{
if (a==0)
{
num = num*10+b;
a--;
continue;
}
num = num*10 + (x/t%10);
a--;
}
return num;
}
bool prim(int x)
{
if (x<=1)
return false;
int q = sqrt(x);
for (int i = 2; i<=q; i++)
{
if (x%i==0)
return false;
}
return true;
}
void bfs(int m, int n)
{
P p,pp;
p.x = m;
p.stp = 0;
queueq;
q.push(p);
while (!q.empty())
{
p = q.front();
q.pop();
if (p.x==n)
{
printf("%d\n", p.stp);
return;
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j <= 9; j++)
{
if (i==0&&j==0)
continue;
int x = change(p.x,i,j);
if (prim(x)&&!book[x])
{
pp.x = x;
pp.stp = p.stp+1;
book[x]=1;
q.push(pp);
}
}
}
}
return;
}
int main(void)
{
int T;
scanf("%d", &T);
while (T--)
{
int m,n;
memset(book,0,sizeof(book));
scanf("%d %d", &m, &n);
book[m]=1;
bfs(m, n);
}
return 0;
}
题意:给定三个字符串S1,S2,S3。 每次进行一步 将S1,S2拼接成 S1[0]S2[0]S1[1]S2[1]….。然后将前半段为新的S1,后半段为新的S2。 问经过多少次更新,可以将S1,S2合并成S3。
思路:用map存合并成的S3所需要的步数。bfs遍历所有情况。如果队列为空则不可能。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
string s1,s2,S;
map<string, int>mp;
int n;
string F(string s1, string s2)
{
string SS;
for (int i = 0; i < n; i++)
{
SS+=s2[i];
SS+=s1[i];
}
return SS;
}
string change(string ss, int x, int y)
{
string s;
for (int i = x; i < y; i++)
s+=ss[i];
return s;
}
int bfs(string s1, string s2)
{
queue<string>q;
string SS = F(s1,s2);
q.push(SS);
mp[SS] = 1;
while (!q.empty())
{
SS = q.front();
if (SS == S)
{
return mp[SS];
}
q.pop();
string S1, S2;
S1 = change(SS, 0, n);
S2 = change(SS, n, 2*n);
string ss = F(S1,S2);
if (mp[ss]==0)
{
mp[ss] = mp[SS]+1;
q.push(ss);
}
}
return -1;
}
int main(void)
{
int T,t=1;
scanf("%d", &T);
while (T--)
{
mp.clear();
cin>>n>>s1>>s2>>S;
int ans = bfs(s1, s2);
printf("%d %d\n", t++, ans);
}
return 0;
}
题意:有两个杯子,有三种操作:
1.FILL(i) 将i杯子接满水。
2.DROP(i) 将i杯子倒空。
3.POUR(i,j) 将i杯子的水倒往j杯子。
问能不能倒出C容量的水,并输出步骤。
思路:模拟队列,分别有6步:
1 ->A 2 ->B 3 A->B 4 B->A 5 A-> 6 B->
进行BFS, 写着比较复杂,但基本都是复制粘贴,注意处理A->B,跟B->A,就好。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int A,B,C;
struct node {
int x,y,rear,stp;
int flag; // 1 ->A 2 ->B 3 A->B 4 B->A 5 A-> 6 B->
}P[100000+100];
int book[300][300];
void out(int x)
{
switch(x)
{
case 1:{
printf("FILL(1)\n");
break;
}
case 2:{
printf("FILL(2)\n");
break;
}
case 3:{
printf("POUR(1,2)\n");
break;
}
case 4:{
printf("POUR(2,1)\n");
break;
}
case 5:{
printf("DROP(1)\n");
break;
}
case 6:{
printf("DROP(2)\n");
}
}
}
void print(int t)
{
if (P[t].rear==-1)
return;
print(P[t].rear);
out(P[t].flag);
return;
}
void bfs()
{
int S=0,E=1;
P[S].x=0;
P[S].y=0;
P[S].stp=0;
P[S].flag=0;
P[S].rear=-1;
book[0][0]=1;
struct node p;
while (S.x==C || P[S].y==C)
{
printf("%d\n",P[S].stp);
print(P[S].rear);
out(P[S].flag);
return;
}
for (int i = 1; i <= 6; i++)
{
P[E].rear = S;
P[E].stp = P[S].stp+1;
P[E].flag = i;
if (i==1&&P[S].x!=A)
{
P[E].x = A;
P[E].y = P[S].y;
}
if (i==2&&P[S].y!=B)
{
P[E].y = B;
P[E].x = P[S].x;
}
if(i==3&&P[S].x!=0&&P[S].y!=B)
{
P[E].y = (P[S].x+P[S].y)>B ? B:(P[S].x+P[S].y);
P[E].x = (P[S].x+P[S].y)>B ? (P[S].x+P[S].y-B):0;
}
if (i==4&&P[S].y!=0&&P[S].x!=A)
{
P[E].x = (P[S].x+P[S].y)>A ? A:(P[S].x+P[S].y);
P[E].y = (P[S].x+P[S].y)>A ? (P[S].x+P[S].y-A):0;
}
if (i==5)
{
P[E].x=0;
P[E].y = P[S].y;
}
if(i==6)
{
P[E].y=0;
P[E].x = P[S].x;
}
if (book[P[E].x][P[E].y]==0)
{
book[P[E].x][P[E].y]=1;
E++;
}
}
S++;
}
printf("impossible\n");
return;
}
int main(void)
{
while (~scanf("%d %d %d", &A, &B, &C))
{
memset(book,0,sizeof(book));
bfs();
}
return 0;
}
题意:有两个小朋友要在一个平面内的草地上点火, 当一个人点燃一块草地之后,每秒火都会向周围四个方向扩散,每人只能点燃一块,问最少的时间将这个平面内的草地烧干净,输出最短的时间,如果不可能输出-1。
思路:m,n只有10,两两枚举所有的“#”,并进行bfs寻找最少的时间。
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
char mp[20][20];
int book[20][20];
int nxt[4][2] = {1,0,0,1,-1,0,0,-1};
typedef struct {
int x, y;
}Point;
int bfs(int x, int y, int xx, int yy)
{
memset(book,inf,sizeof(book));
queue q;
Point p,pp;
p.x = x;
p.y = y;
q.push(p);
p.x = xx;
p.y = yy;
q.push(p);
book[x][y]=0;
book[xx][yy]=0;
while (!q.empty())
{
p = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
pp.x = p.x+nxt[i][0];
pp.y = p.y+nxt[i][1];
if (pp.x<0||pp.y<0||pp.x>=n||pp.y>=m)
continue;
if (mp[pp.x][pp.y]!='.' && book[pp.x][pp.y]>book[p.x][p.y]+1)
{
book[pp.x][pp.y]=book[p.x][p.y]+1;
q.push(pp);
}
}
}
int ans = -1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (mp[i][j]=='#')
{
if (book[i][j]==inf)
return inf;
ans = max(book[i][j],ans);
}
}
}
return ans;
}
int main(void)
{
int T,t=1;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf(" %s", mp[i]);
}
int ans = inf;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (mp[i][j]=='#')
{
for (int I = 0; I < n; I++)
{
for (int J = 0; J < m; J++)
{
if (mp[I][J]=='#')
{
int tmp = bfs(i,j,I,J);
ans = min(ans, tmp);
}
}
}
}
}
}
printf("Case %d: %d\n", t++, ans==inf?-1:ans);
}
return 0;
}
题意:一个人在迷宫里面,迷宫着火了,火每秒向周围四个方向扩散,人每秒走一步,问人能不能逃出去。
思路:先对整个地图的所有“F”进行BFS,找到地图上所有点被点燃的最短时间,然后再对人进行BFS。
注意:不止有一处着火。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using namespace std;
int m,n;
char mp[1100][1100];
int nxt[4][2]={1,0, 0,1, -1,0, 0,-1};
int book[1100][1100];
void bfs_fire()
{
memset(book,inf,sizeof(book));
queue<int>qx,qy;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (mp[i][j] == 'F')
{
book[i][j]=0;
qx.push(i);
qy.push(j);
}
}
}
while (!qx.empty())
{
int x = qx.front();
int y = qy.front();
qx.pop();
qy.pop();
for (int i = 0; i < 4; i++)
{
int xx = x+nxt[i][0];
int yy = y+nxt[i][1];
if (xx<0||yy<0||xx>=m||yy>=n)
continue;
if (mp[xx][yy]!='.')
continue;
if (book[x][y]+1>=book[xx][yy])
continue;
book[xx][yy]=book[x][y]+1;
qx.push(xx);
qy.push(yy);
}
}
return;
}
int bfs2(int x, int y)
{
queue<int>qx,qy;
qx.push(x);
qy.push(y);
book[x][y]=0;
while (!qx.empty())
{
x = qx.front();
y = qy.front();
qx.pop();
qy.pop();
for (int i = 0; i < 4; i++)
{
int xx = x+nxt[i][0];
int yy = y+nxt[i][1];
if (mp[xx][yy]!='.')
continue;
if (book[x][y]+1 >= book[xx][yy])
continue;
if (xx==m-1||yy==n-1||xx==0||yy==0)
return book[x][y]+2;
book[xx][yy] = book[x][y]+1;
qx.push(xx);
qy.push(yy);
}
}
return -1;
}
int main(void)
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &m, &n);
int jx,jy;
for (int i = 0; i < m; i++)
{
scanf(" %s", mp[i]);
for (int j = 0; j < n; j++)
{
if (mp[i][j]=='J')
{
jx=i;
jy=j;
}
}
}
if (jx==m-1||jy==n-1||jx==0||jy==0)
{
printf("1\n");
continue;
}
int ans = -1;
bfs_fire();
ans = bfs2(jx,jy);
if (ans==-1)
printf("IMPOSSIBLE\n");
else
printf("%d\n",ans);
}
return 0;
}
题意:中文题。。
思路 : 数组模拟队列,递归回溯输出。
#include
#include
#include
#include
#include
#include
using namespace std;
struct node{
int x,y,s;
}Step[10000+100];
int mp[10][10];
void print(int S)
{
if (Step[S].x==0 && Step[S].y==0)
return;
print(Step[S].s);
printf("(%d, %d)\n",Step[S].x, Step[S].y);
return;
}
void bfs(int x, int y)
{
int nxt[4][2] = {1,0, 0,1, -1,0, 0,-1};
int S = 0, E=1;
Step[S].x = x;
Step[S].y = y;
Step[S].s = 0;
while (Sfor (int i = 0; i < 4; i++)
{
int nx = Step[S].x+nxt[i][0];
int ny = Step[S].y+nxt[i][1];
if (nx<0||ny<0||nx==5||ny==5)
continue;
if (mp[nx][ny]==0)
{
mp[nx][ny]=1;
Step[E].x = nx;
Step[E].y = ny;
Step[E].s = S;
E++;
}
if (nx==4&&ny==4)
{
print(S);
return;
}
}
S++;
}
}
int main(void)
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
scanf("%d", &mp[i][j]);
}
}
mp[0][0]=1;
printf("(0, 0)\n");
bfs(0,0);
printf("(4, 4)\n");
return 0;
}
题意: 问有多少个连通区域。
思路: 循环,找到“@”就进行dfs,ans++,并标记为“*”;
#include
#include
#include
#include
#include
#include
using namespace std;
int m,n;
char mp[120][120];
int nxt[8][2]={1,0, 1,1, 0,1, -1,1, -1,0, -1,-1, 0,-1, 1,-1};
void dfs(int x, int y)
{
for (int i = 0; i < 8; i++)
{
int nx = x + nxt[i][0];
int ny = y + nxt[i][1];
if (nx<0||ny<0||nx>=m||ny>=n)
continue;
if (mp[nx][ny]=='@')
{
mp[nx][ny]='*';
dfs(nx,ny);
}
}
return;
}
int main(void)
{
while (scanf("%d %d", &m, &n))
{
if (m==0 && n==0)
break;
for (int i = 0; i < m; i++)
scanf(" %s", mp[i]);
int ans = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (mp[i][j]=='@')
{
ans++;
mp[i][j]='*';
dfs(i,j);
}
}
}
printf("%d\n", ans);
}
return 0;
}
题意:中文题。
思路:三个瓶子来回倒, 一共六种情况,分别列举BFS。注意处理瓶子满的,或者空着的情况。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int S,N,M;
int book[120][120][120];
typedef struct node{
int x,y,z;
int stp;
}P;
bool check(P p)
{
if (p.x==p.y&&p.x==S/2)
return true;
if (p.x==p.z&&p.x==S/2)
return true;
if (p.z==p.y&&p.y==S/2)
return true;
return false;
}
void bfs()
{
queue q;
P p,pp;
p.x = S;
p.y = 0;
p.z = 0;
p.stp = 0;
book[p.x][p.y][p.z]=1;
q.push(p);
while (!q.empty())
{
p=q.front();
q.pop();
if (check(p))
{
printf("%d\n", p.stp);
return ;
}
for (int i = 1; i<=6; i++)
{
pp.x = p.x;
pp.y = p.y;
pp.z = p.z;
pp.stp = p.stp+1;
if (i==1)
{
pp.x = (p.x+p.y)>N? (p.x+p.y-N):0;
pp.y = (p.x+p.y)>N? N:(p.x+p.y);
}
if (i==2)
{
pp.x = (p.x+p.z)>M? (p.x+p.z-M):0;
pp.z = (p.x+p.z)>M? M:(p.x+p.z);
}
if (i==3)
{
pp.x = (p.x+p.y)>S? S:(p.x+p.y);
pp.y = (p.x+p.y)>S? (p.x+p.y-S):0;
}
if (i==4)
{
pp.z = (p.y+p.z)>M? M:(p.y+p.z);
pp.y = (p.z+p.y)>M? (p.z+p.y-M):0;
}
if (i==5)
{
pp.x = (p.x+p.z)>S? S:(p.x+p.z);
pp.z = (p.x+p.z)>S? (p.x+p.z-S):0;
}
if (i==6)
{
pp.y = (p.y+p.z)>N? N:(p.y+p.z);
pp.z = (p.y+p.z)>N? (p.y+p.z-N):0;
}
if (!book[pp.x][pp.y][pp.z])
{
book[pp.x][pp.y][pp.z]=1;
q.push(pp);
}
}
}
printf("NO\n");
return ;
}
int main(void)
{
while (~scanf("%d %d %d", &S, &N, &M))
{
if (S==0&&M==0&&N==0)
break;
if (S&1)
{
printf("NO\n");
continue;
}
memset(book,0,sizeof(book));
bfs();
}
return 0;
}
题意:Y和M要在“@”的地方见面, 地图上有不止一个“@”,两个人每11分钟移动一次,只能向上下左右四个方向移动,问他们两个在“@”处见面的最少时间。
思路:分别BFS求出两个人到达所有“@”的时间,再求最小。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct node{
int x, y, stp;
}P;
int num[300][300];
char mp[300][300];
int book[300][300];
int m,n;
void bfs(int x, int y)
{
int nxt[4][2] = {0,1, 1,0, -1,0, 0,-1};
queue q;
P p, pp;
p.x = x;
p.y = y;
p.stp = 0;
q.push(p);
book[x][y]=1;
while (!q.empty())
{
p=q.front();
q.pop();
pp.stp = p.stp+1;
for (int i = 0; i < 4; i++)
{
pp.x = p.x+nxt[i][0];
pp.y = p.y+nxt[i][1];
if (pp.x<0||pp.y<0||pp.x>=m||pp.y>=n)
continue;
if (!book[pp.x][pp.y] && mp[pp.x][pp.y]!='#')
{
book[pp.x][pp.y]=1;
if (mp[pp.x][pp.y]=='@')
{
num[pp.x][pp.y]+=pp.stp;
}
q.push(pp);
}
}
}
return;
}
int main(void)
{
while (~scanf("%d %d", &m, &n))
{
for (int i = 0; i < m; i++)
scanf(" %s", mp[i]);
memset(num,0,sizeof(num));
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (mp[i][j]=='Y')
{
memset(book,0,sizeof(book));
bfs(i,j);
}
if (mp[i][j]=='M')
{
memset(book,0,sizeof(book));
bfs(i,j);
}
}
}
int Min = 50000;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (mp[i][j]=='@' && num[i][j]0)
{
Min = num[i][j];
}
}
}
printf("%d\n", Min*11);
}
return 0;
}