快要期末考試來了,最近也沒怎麼看算法,整理下我前段時間做的搜索超級水題吧,多做點搜索水題也算是爲以後學習圖論做點準備,baka哥說圖論的算法基本都是DFS和BFS。
POJ 1321 棋盤問題
鏈接:http://poj.org/problem?id=1321
代碼:
#include<cstdio>
#include<cstring>
char mapn[9][9];
int visit[9];//記錄列數是否相同
int n,k,tot;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void DFS(int a,int step)//a表示行號
{
if(step==k)
{
tot++;
return ;
}
if(a>=n)
return ;
for(int i=0;i<n;i++)
{
if(!visit[i]&&mapn[a][i]=='#')
{
visit[i]=1;
DFS(a+1,step+1);
visit[i]=0;
}
}
DFS(a+1,step); //第a+1行不放棋子的情況
}
int main()
{
int i;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==-1&&k==-1)
break;
tot=0;
memset(visit,0,sizeof(visit));
for(i=0;i<n;i++)
scanf("%s",mapn[i]);
DFS(0,0);
printf("%d\n",tot);
}
return 0;
}
HDU 1016 Prime RIng Problem
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1016
代碼:
#include<cstdio>
#include<cstring>
int n;
int isp[40],visit[21],A[21];
bool is_prime(int m)
{
if(m==2||m==3)
return 1;
for(int i=2;i*i<=m;i++)
if(m%i==0)
return 0;
return 1;
}
void DFS(int cur)
{
if(cur==n&&isp[A[0]+A[cur-1]]) //遞歸邊界
{
for(int i=0;i<n-1;i++)
printf("%d ",A[i]);
printf("%d\n",A[n-1]);
}
else
for(int i=1;i<=n;i++)
{
if(!visit[i]&&isp[i+A[cur-1]])//如果i沒有用過,是否和相鄰的加起來是素數
{
A[cur]=i;
visit[i]=1;
DFS(cur+1);
visit[i]=0;
}
}
}
int main()
{
for(int i=2;i<=40;i++)
isp[i]=is_prime(i);
int k=1;
while(scanf("%d",&n)!=EOF)
{
printf("Case %d:\n",k);
memset(visit,0,sizeof(visit));
A[0]=1;
k++;
visit[0]=1;
visit[1]=1;
DFS(1);
printf("\n");
}
return 0;
}
HDU 1253勝利大逃亡
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1253
代碼:
#include<stdio.h>
#include<queue>
using namespace std ;
int a, b, c, T;
int map[51][51][51] ;
int dir[6][3] ={{1,0,0},{-1,0,0},{0,0,1},{0,0,-1},{0,1,0},{0,-1,0}};
struct node
{
int x,y,z,step;
}start;
void BFS()
{
queue<node> q ;
node cur,next;
start.x=0;
start.y=0;
start.z=0;
start.step=0;
map[0][0][0] = 1 ;
q.push(start) ;
while(!q.empty())
{
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==a-1&&next.y==b-1&&next.z==c-1&&cur.step<=T)
{
printf("%d\n", cur.step+1) ;
return ;
}
if(next.x>=0&&next.x<a&&next.y>=0&&next.y<b&&next.z>=0&&next.z<c&&!map[next.x][next.y][next.z])
{
map[next.x][next.y][next.z] = 1 ;
next.step=cur.step+1;
q.push(next) ;
}
}
}
printf("-1\n") ;
return ;
}
int main()
{
int t ;
scanf("%d", &t) ;
while(t--)
{
scanf("%d%d%d%d", &a, &b, &c, &T) ;
for(int i=0; i<a; i++)
for(int j=0; j<b; j++)
for(int k=0; k<c; k++)
scanf("%d", &map[i][j][k]) ;
if(map[a-1][b-1][c-1]||a+b+c-3>T) //終點在牆上或者距離終點的最短距離大於要求時間
{
printf("-1\n") ;
continue ;
}
if(a==1&&b==1&&c==1)
{
printf("0\n") ;
continue ;
}
BFS() ;
}
return 0 ;
}
HDU 1312 Red and Black
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1312
代碼:
#include<cstdio>
#include<queue>
using std::queue;
int n,m;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
char map[21][21];
struct point
{
int x,y;
}start;
int num;
int BFS(int a,int b)
{
int i;
queue<point> q;
point cur,next;
start.x=a;
start.y=b;
q.push(start);
num=1;
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&map[next.x][next.y]!='#')
{
num++;
map[next.x][next.y]='#';
q.push(next);
}
}
}
return num;
}
int main()
{
int i,j,si,sj;
while(scanf("%d%d",&m,&n)!=EOF)
{
if(n==0&&m==0)
break;
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='@')
{
si=i;
sj=j;
}
}
getchar();
}
map[si][sj]='#';
printf("%d\n",BFS(si,sj));
}
return 0;
}
HDU 2553 N皇后問題
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
數組記錄代碼:
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
int n,tot;
int vis[3][22];
void dfs(int cur)
{
if(cur==n)
{
tot++;
return ;
}
else
for(int i=0; i<n; i++)
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]) //主對角線加n爲保證數組下標不小於0,小白書上有說明
{
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
dfs(cur+1);
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
}
}
int main()
{
int result[11];
for(n=0; n<11; n++) //在外邊打表,不然會超時
{
memset(vis,0,sizeof(vis));
tot=0;
dfs(0);
result[n]=tot;
}
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
printf("%d\n",result[n]);
}
return 0;
}
直接DFS代碼:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n,ans;
int map[15];
int visit[15];
int sol[15];
void dfs(int k)
{
int i,j,flag;
if(k==n+1)
{
ans++;
return;
}
for(i=1;i<=n;i++)
if(!visit[i]) //各行棋子不能在同一豎
{
map[k]=i;
flag=1;
for(j=1;j<=k-1;j++)
if((abs(map[k]-map[j]))==abs((k-j))) //判斷是否在同一斜線上
{
flag=0;
break;
}
if(flag)
{
visit[i]=1;
dfs(k+1);
visit[i]=0; //釋放第i列,進行下一次搜索
}
}
}
int main()
{
int i;
for(i=1;i<=10;i++)
{
ans=0;
n=i;
memset(map,0,sizeof(map));
memset(visit,0,sizeof(visit));
dfs(1);
sol[i]=ans;
}
while(scanf("%d",&n),n)
printf("%d\n",sol[n]);
return 0;
}
HDU 1241 Oil Deposits
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1241
這也是一道很水的BFS,只要找出相連的區域塊的數目就好。
代碼:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m;
char map[101][101];
int dir[8][2]={{0,1},{1,1},{1,0},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
struct point
{
int x,y;
}start;
void BFS(int a,int b)
{
start.x=a;
start.y=b;
queue<point> q;
int i;
point cur,next;
q.push(start);
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=0;i<8;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m)
{
if(map[next.x][next.y]=='@')
{
map[next.x][next.y]='*';
q.push(next);
}
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
int count=0;
for(i=0;i<n;i++)
scanf("%s",map[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(map[i][j]=='@')
{
map[i][j]='*';
BFS(i,j);
count++;
}
}
printf("%d\n",count);
}
return 0;
}
HDU 1240 Asteroids
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1240
這是一道3維的BFS,在處理座標時注意點,基本就可以過了,跟普通的寬搜沒什麼兩樣。
代碼:
#include<cstdio>
#include<queue>
using namespace std;
struct point
{
int x,y,z,steps;
};
point start;
int dx,dy,dz;
int n;
char map[11][11][11];
int dir[6][3]={{1,0,0}, {-1,0,0}, {0,1,0}, {0,-1,0}, {0,0,1}, {0,0,-1}};
int bfs(point start)
{
queue<point>q;
int i;
point cur,next;
if(start.x==dx&&start.y==dy&&start.z==dz)//考慮起點和終點相同的情況
return 0;
start.steps=0;
map[start.x][start.y][start.z]='X';
q.push(start);
while(!q.empty())
{
cur=q.front();//取隊首元素
q.pop();
for(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==dx && next.y==dy && next.z==dz) //下一步就是目的地
{
return cur.steps+1;
}
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<n&&next.z>=0&&next.z<n)//下一步不越界
if(map[next.x][next.y][next.z]!='X') //下一步不是星星
{
map[next.x][next.y][next.z]='X';
next.steps=cur.steps+1;
q.push(next);
}
}
}
return -1;
}
int main()
{
char str[10];
int i,j,step;
while(scanf("START %d",&n)!=EOF)
{
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
for(int k=0;k<n;k++)
scanf("%c",&map[j][k][i]);
getchar();
}
}
scanf("%d%d%d",&start.x, &start.y, &start.z);
scanf("%d%d%d",&dx, &dy, &dz);
scanf("%s",str);
gets(str);
step=bfs(start);
if(step>=0)
printf("%d %d\n",n,step);
else
printf("NO ROUTE\n");
}
return 0;
}
HDU1372 Knight Movies
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1372
這道題只要讀懂題目就很容易可以搞定,是棋盤上馬走的方向就是BFS搜索時的方向,棋盤是8*8,只不過用字母a到h表示。剛開始一直不明白題意,連樣例都沒看來,後來讀懂之後真是個超級大水題。嘻嘻,這道題寫的時候借用了下baka哥的頭文件,感覺酷酷的樣子,相信他不會怪我的吧,知道我這麼水,也寫不出什麼好的頭文件。
代碼:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
int dir[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,-1},{-2,1}};
struct point
{
int x,y;
int step;
}start;
int dx,dy;
int visit[10][10];
int BFS(int x,int y)
{
int i;
queue<point> q;
point cur,next;
start.x=x;
start.y=y;
start.step=0;
q.push(start);
while(!q.empty())
{
cur=q.front();
q.pop();
if(cur.x==dx&&cur.y==dy)
return cur.step ;
for(i=0;i<8;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<8&&next.y>=0&&next.y<8&&!visit[next.x][next.y])
{
visit[next.x][next.y]=1;
next.step=cur.step+1;
q.push(next);
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
char a[3],b[3];
int sx,sy,sum;
while(scanf("%s%s",a,b)!=EOF)
{
printf("To get from %s to %s takes ",a,b);
sx=a[0]-'a';
sy=a[1]-'0'-1;
dx=b[0]-'a';
dy=b[1]-'0'-1;
memset(visit,0,sizeof(visit));
visit[sx][sy]=1;
sum=BFS(sx,sy);
printf("%d knight moves.\n",sum);
}
return 0;
}