POJ——1321
题意:在矩阵特定区域放置k个棋子有多少种放法
题解:dfs,从第一行开始
#include<iostream>
#include<string>
using namespace std;
char a[9][9];
int cl[9];
int n, k, ans;
void dfs(int r, int num)
{
if (num == k) {
ans++;
return;
}
if (r > n)
return;
int i;
for (i = 1; i <= n; i++) {
if (a[r][i] == '#' && cl[i] == 0) {
cl[i] = 1;
dfs(r + 1, num + 1);
cl[i] = 0;
}
}
dfs(r + 1, num);
}
int main()
{
while (~scanf_s("%d%d", &n, &k)) {
if (n == -1 && k == -1)
break;
getchar();
int i, j;
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++)
cin >> a[i][j];
}
memset(cl, 0, sizeof(cl));
ans = 0;
dfs(1, 0);
cout << ans << endl;
}
return 0;
}
POJ——2251
题意:在三维迷宫中找到从起点‘S’到终点‘E’的最短路径
题解:建立三维数组,bfs
#include <iostream>
#include<queue>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
#define maxn 31
char a[maxn][maxn][maxn];
int d[maxn][maxn][maxn];
int dir[6][3]={{-1,0,0},{1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};//2向右3向左4向上
int sum=0;
int L,R,C;
struct node{
int x,y,z;
};
node start,ed;
int bfs()
{
queue<node> Q;
Q.push(start);
node cur;
node next;
while(Q.size())
{
cur=Q.front();
Q.pop();
for(int i=0;i<6;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.z=cur.z+dir[i][2];
if(next.x>=0&&next.x<R&&next.y>=0&&next.y<C&&next.z>=0&&next.z<L&&a[next.z][next.x][next.y]!='#'&&d[next.z][next.x][next.y]==0)
{
//a[cur.z][cur.x][cur.y]='#'; 这样操作的话在栈中的点,也有可能到达当前的next点,
//若用d[next.z][next.x][next.y]==0判断,只要到达next,就不会再判断
d[next.z][next.x][next.y]=d[cur.z][cur.x][cur.y]+1;
if(next.x==ed.x&&next.y==ed.y&&next.z==ed.z)
return d[ed.z][ed.x][ed.y];
Q.push(next);
}
}
}
return -1;
}
int main()
{
while(cin>>L>>R>>C&&(L+R+C)!=0)
{
sum=0;
memset(d,0,sizeof(d));
for(int i=0;i<L;i++)
for(int j=0;j<R;j++)
for(int k=0;k<C;k++)
{
cin>>a[i][j][k];
if(a[i][j][k]=='S')
{
start.z=i;start.x=j;start.y=k;
}
else if(a[i][j][k]=='E')
{
ed.z=i;ed.x=j;ed.y=k;
}
}
// cout<<start.x<< " "<<start.y<<" "<<start.z<<endl;
// cout<<ed.x<<" "<<ed.y<<" "<<ed.z<<endl;
if( bfs()==-1)
printf("Trapped!\n");
else
printf("Escaped in %d minute(s).\n",d[ed.z][ed.x][ed.y]);
}
return 0;
}
POJ——3278
题意:可以对数n进行三种操作——n+1,n-1和n*2,求数n变换到k的最短路径
题解:bfs
#include<iostream>
#include<queue>
#include<string>
using namespace std;
int n, m;
const int MAX = 1e5+5;
int b[MAX];
int t[MAX];
int bfs()
{
memset(b, 0, sizeof(b));
memset(t, 0, sizeof(t));
queue<int>q;
q.push(n);
b[n] = 1;
int i;
while (!q.empty()) {
int cur, nex;
cur = q.front();
q.pop();
if (cur == m)
return t[cur];
for (i = 0; i < 3; i++) {
if (i == 0)
nex = cur + 1;
if (i == 1)
nex = cur - 1;
if (i == 2)
nex = cur * 2;
if (nex <= 1e5 && nex >= 0 && (!b[nex])) {
t[nex] = t[cur] + 1;
b[nex] = 1;
q.push(nex);
}
}
}
return -1;
}
int main()
{
cin >> n >> m;
cout << bfs() << endl;
return 0;
}
POJ——1383
题意:在迷宫中寻找最长相连的可走方块个数
题解:bfs
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1005
using namespace std;
int n,m,t;
char a[maxn][maxn];
int used[maxn][maxn];//判重
const int walkx[4]={1,-1,0,0},walky[4]={0,0,1,-1};//控制走的方向
struct node{
int x;
int y;
int t;
node(){}
node(int xx,int yy,int tim){
x=xx;
y=yy;
t=tim;
}
};
int is_check(int x,int y){
if(x<=0||y<=0||x>n||y>m||used[x][y]==1||a[x][y]=='#') return 0;
else return 1;
}
node bfs(int sx,int sy){//sx,sy为起点
memset(used,0,sizeof(used));
queue<node>q;
q.push(node(sx,sy,0));
node now,nex;
int tx,ty;
int maxt=0,maxx=sx,maxy=sy;
while(!q.empty()){
now=q.front();
q.pop();
if(now.t>maxt){
maxx=now.x;
maxy=now.y;
maxt=now.t;
}
for(int i=0;i<4;i++){
tx=now.x+walkx[i];
ty=now.y+walky[i];
if(is_check(tx,ty)){
used[tx][ty]=1;
q.push(node(tx,ty,now.t+1));
}
}
}
return node(maxx,maxy,maxt);
}
int main(){
char tmp[maxn];
scanf("%d",&t);
while(t--){
scanf("%d %d\n",&n,&m);
swap(n,m);
int xx,yy;
xx=yy=-1;
for(int i=1;i<=n;i++){
scanf("%s",tmp+1);
for(int j=1;j<=m;j++){
a[i][j]=tmp[j];
if(a[i][j]=='.'&&xx==-1&&yy==-1){
xx=i;
yy=j;
}
}
}
node tmp1=bfs(xx,yy);
node tmp2=bfs(tmp1.x,tmp1.y);
printf("Maximum rope length is %d.\n",tmp2.t);
}
}
POJ——2243
题意:在棋盘上给定起点和终点,计算棋子“马”从起点到终点所需最短步数
题解:bfs
#include<iostream>
#include<queue>
#include<string>
using namespace std;
int book[8][8];
struct node {
int x, y;
int t;
};
node st, ed;
const int tr[8][2] = { {2,1},{2,-1}, {-2,1},{-2,-1}, {1,2},{1,-2}, {-1,2},{-1,-2} };
int bfs()
{
queue<node>q;
memset(book, 0, sizeof(book));
book[st.x][st.y] = 1;
q.push(st);
while (!q.empty()) {
node cur, nex;
cur = q.front();
q.pop();
if (cur.x == ed.x && cur.y == ed.y)
return cur.t;
int i;
for (i = 0; i < 8; i++) {
nex.x = cur.x + tr[i][0];
nex.y = cur.y + tr[i][1];
nex.t = cur.t + 1;
if (nex.x >= 0 && nex.x < 8 && nex.y >= 0 && nex.y < 8 && book[nex.x][nex.y] == 0) {
book[nex.x][nex.y] = 1;
q.push(nex);
}
}
}
return -1;
}
int main()
{
int y1, y2;
char x1, x2;
while (cin>>x1>>y1>>x2>>y2) {
st.x = x1 - 'a';
st.y = y1 - 1;
st.t = 0;
ed.x = x2 - 'a';
ed.y = y2 - 1;
ed.t = 0;
int ans = bfs();
printf("To get from %c%d to %c%d takes %d knight moves.\n", x1, y1, x2, y2, ans);
}
return 0;
}
POJ——3279
题意:给定一个01矩阵,当一个单位翻转时,其相邻的单位数字也要翻转。求使该矩阵变为0矩阵的翻转次数最少,字典排序最小的翻转矩阵
题解:二进制枚举+bfs,设翻转矩阵为f,对f的第一行枚举所有情况,再往下得出最后一行看是否全为零
#include<iostream>
#include<queue>
#include<string>
using namespace std;
const int MAX = 20;
int map[20][20], f[20][20];
int m, n;
const int wr[4][2] = { {0,0},{-1,0},{0,-1},{0,1} };
int bw()
{
int i, j, k;
for (i = 1; i < m; i++) {
for (j = 1; j <= n; j++) {
int t = map[i][j];
for (k = 0; k < 4; k++) {
int tx = i + wr[k][0];
int ty = j + wr[k][1];
t += f[tx][ty];
}
if (t & 1)
f[i + 1][j] = 1;
}
}
for (j = 1; j <= n; j++) {
int t = map[i][j];
for (k = 0; k < 4; k++) {
int tx = i + wr[k][0];
int ty = j + wr[k][1];
t += f[tx][ty];
}
if (t & 1)
return -1;
}
int ans = 0;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
ans += f[i][j];
}
}
return ans;
}
int main()
{
cin >> m >> n;
int i, j, k, l;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++)
cin >> map[i][j];
}
int ans = 0x3f3f3f3f;
int tmp[20][20];
for (i = 0; i < (1 << n); i++) {
memset(f, 0, sizeof(f));
for (j = 0; j < n; j++) {
f[1][j + 1] = (i >> j) & 1;
}
int t = bw();
if (t == -1)
continue;
if (t < ans) {
ans = t;
for (k = 1; k <= m; k++) {
for (l = 1; l <= n; l++)
tmp[k][l] = f[k][l];
}
}
}
if (ans == 0x3f3f3f3f)
cout << "IMPOSSIBLE" << endl;
else {
for (k = 1; k <= m; k++) {
for (l = 1; l <= n; l++)
cout << tmp[k][l] << " ";
cout << endl;
}
}
return 0;
}
POJ——3669
题意:第一象限内有m颗陨石再不同时刻砸到不同坐标上,这些坐标相邻的坐标也会被摧毁,被摧毁后的坐标不能再经过,求从原点开始到安全地点所需走的最短步数
题解:初始化地图数组m全为-1,在通过输入修改被摧毁的坐标的m上的值为其被摧毁的最初时刻,再bfs
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
int map[305][305];
const int g[5][2] = { {0,0}, {0,1},{0,-1},{1,0},{-1,0} };
struct node {
int x, y;
int t;
};
int bfs()
{
if (map[0][0] == 0) return -1;
if (map[0][0] == -1) return 0;
node st;
st.x = 0; st.y = 0; st.t = 0;
queue<node>q;
q.push(st);
while (!q.empty()) {
node cur, nex;
cur = q.front();
q.pop();
int i;
for (i = 0; i < 5; i++) {
nex.t = cur.t + 1;
nex.x = cur.x + g[i][0];
nex.y = cur.y + g[i][1];
if (nex.x < 0 || nex.x>400 || nex.y < 0 || nex.y>400)
continue;
if (map[nex.x][nex.y] == -1)return nex.t;
if (map[nex.x][nex.y] <= nex.t)continue;
map[nex.x][nex.y] = nex.t;
q.push(nex);
}
}
return -1;
}
int main()
{
int m;
cin >> m;
int i, x, y, t, j;
memset(map, -1, sizeof(map));
for (i = 0; i < m; i++) {
cin >> x >> y >> t;
for (j = 0; j < 5; j++) {
int tx = x + g[j][0];
int ty = y + g[j][1];
if (tx < 0 || tx>400 && ty < 0 && ty>400)
continue;
if (map[tx][ty] == -1) map[tx][ty] = t;
else map[tx][ty] = min(map[tx][ty], t);
}
}
cout << bfs() << endl;
return 0;
}
POJ——3126
题意:给两个四位素数m,n,每次只能改变某一位的数字,且改变后的数也要是素数,求从m变换到n所需最短步数
题解:素数筛(复习埃氏筛和欧式筛)+bfs
#include<iostream>
#include<queue>
#include<string>
using namespace std;
const int MAX = 1e4;
int m, n;
int prime[MAX], b[MAX];
struct node {
int v, t;
};
void biuld()
{
int i;
memset(prime, 1, sizeof(prime));
prime[1] = 0;
for (i = 2; i * i < MAX; i++) {
if (prime[i]) {
for (int j = i * i; j < MAX; j+=i) {
prime[j] = 0;
}
}
}
}
int find(int x, int i, int j)
{
if (i == 1)
x = x / 10 * 10 + j;
if (i == 2)
x = x / 100 * 100 + j * 10 + x % 10;
if (i == 3)
x = x / 1000 * 1000 + j * 100 + x % 100;
if (i == 4)
x = j * 1000 + x % 1000;
return x;
}
int bfs()
{
queue<node>q;
node f;
f.v = m; f.t = 0;
q.push(f);
memset(b, 0, sizeof(b));
b[m] = 1;
while (!q.empty()) {
node cur, nex;
cur = q.front();
q.pop();
if (cur.v == n)
return cur.t;
int i, j;
for (i = 1; i <= 4; i++) {
for (j = 0; j <= 9; j++) {
if (i == 4 && j == 0)
continue;
int tmp = find(cur.v, i, j);
if (prime[tmp] && !b[tmp]) {
nex.t = cur.t + 1;
nex.v = tmp;
b[tmp] = 1;
q.push(nex);
}
}
}
}
return -1;
}
int main()
{
biuld();
int t;
cin >> t;
while (t--) {
cin >> m >> n;
int ans = bfs();
if (ans != -1)
cout << bfs() << endl;
else
cout << "Impossible" << endl;
}
return 0;
}
POJ——3087
题意:题目很长,意思是 先给你两个长度一样的初始状态字符串s1,s2和一个大小为两倍的最终状态的s12,按照s2的第一个先放在s12第一个再依次是s1,s2,s1…,排完后再按照长度前一半是s1新状态,后一半是s2新状态, 重复以上操作,看得到s12是否有和 最初给的最终状态的s12相同的,有输出步数,没有就输出-1.
题解:bfs+字符串处理
#include<iostream>
#include<queue>
#include<string>
#include<map>
using namespace std;
struct node {
string s1, s2, s12;
int t;
};
string shuffle(int c, string s1, string s2)
{
string s12;
int i;
for (i = 0; i < 2 * c; i += 2) {
s12 += s1[i / 2];
s12 += s2[i / 2];
}
return s12;
}
int bfs(string s1, string s2, string s12, int c)
{
map<string, int>m;
queue<node>q;
node fs;
fs.s1 = s1; fs.s2 = s2; fs.t = 1;
fs.s12 = shuffle(c, fs.s2, fs.s1);
q.push(fs);
while (!q.empty()) {
node cur, nex;
cur = q.front();
q.pop();
if (cur.s12 == s12)
return cur.t;
if (m[cur.s12] == 0) {
nex.s1 = cur.s12.substr(0, c);
nex.s2 = cur.s12.substr(c, c);
nex.s12 = shuffle(c, nex.s2, nex.s1);
nex.t = cur.t + 1;
m[cur.s12] = 1;
q.push(nex);
}
else
continue;
}
return -1;
}
int main()
{
int n;
cin >> n;
int tmp = n;
while (n--) {
string s1, s2, s12;
int c;
cin >> c >> s1 >> s2 >> s12;
int ans = bfs(s1, s2, s12, c);
cout << tmp - n << " " << ans << endl;
}
return 0;
}