1、棋盤問題 【POJ - 1321 】
題意
dfs板子題
代碼
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[10][10];//記錄棋盤位置
int put[10];// 記錄一列是否已放棋子
int n, k; //矩陣寬,放棋子數目
int plan, sum; // 方案數和棋子數
void dfs(int hang){
if(k==sum){
plan++;
return;
}
if(hang>=n)//到最後一行
return;
for(int j=0;j<n;j++)
if(put[j]==0&&a[hang][j]=='#'){//這列沒放棋子且可以放棋子
put[j]=1;//標記
sum++;
dfs(hang+1);//繼續往下
put[j]=0;//改回來方便下一行判斷
sum--;
}
dfs(hang+1);
}
int main() {
while(scanf("%d%d",&n,&k)&& n != -1 && k != -1) {
plan=0;sum=0;
for(int i=0;i<n;i++) scanf("%s",&a[i]);
memset(put,0,sizeof(put));
dfs(0);
printf("%d\n",plan);
}
return 0;
}
2、Dungeon Master【POJ2251】
題意概括:
三維地牢,#不能走,.能走,S起點,E終點,求最短路徑
bfs,難點:有六個方向;爲找到最短路徑,使用優先隊列,讓步數step小的先出隊。
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
int sx,sy,sz;
int ex,ey,ez;
int a,b,c;
char mp[35][35][35];//記錄地圖
int vis[35][35][35];//標記是否走過
int base[6][3]= {{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}}; //六個方向
struct node {
int x,y,z;//位置
int step;//步數
friend bool operator<(node a,node b)
//默認的優先隊列是從大到小,要讓步數小的先出來,即時間少,重載<
{
return a.step>b.step;//優先隊列,步數小的先訪問
}
};
priority_queue<node>q;
void bfs() {
node p;
p.x=sx;p.y=sy;p.z=sz;p.step=0;//初始化
vis[sx][sy][sz]=1;
q.push(p);
while(!q.empty()){
node s=q.top();
q.pop();
if(s.x==ex&&s.y==ey&&s.z==ez){//到達終點
printf("Escaped in %d minute(s).\n",s.step);
return;
}
for(int i=0;i<6;i++){//六種走法
int xx=s.x+base[i][0];
int yy=s.y+base[i][1];
int zz=s.z+base[i][2];
if(mp[xx][yy][zz]!='#'&&xx>=0&&xx<a&&yy>=0&&yy<b&&zz>=0&&zz<c&&!vis[xx][yy][zz]){//能不能走
node e;
e.x=xx;e.y=yy;e.z=zz;
e.step=s.step+1;//!!最後輸出的隊列最上面的node,確保它的step是最終的step,即每次在前一個點上加一
vis[e.x][e.y][e.z]=1;
q.push(e);
}
}
}
cout<<"Trapped!"<<endl;
}
int main() {
while(cin>>a>>b>>c,a+b+c){
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
cin>>mp[i][j];//一次輸入一行
for(int k=0;k<c;k++){
if(mp[i][j][k]=='S'){
sx=i;sy=j;sz=k;
}
if(mp[i][j][k]=='E'){
ex=i;ey=j;ez=k;
}
}
}
}
memset(vis,0,sizeof(vis));//每次都要初始化
bfs();
}
}
推薦題解:
https://www.cnblogs.com/sky-stars/p/10963418.html
3、Catch That Cow 【POJ - 3278】
題意
有一個農民和一頭牛,他們在一個數軸上,牛在k位置保持不動,農戶開始時在n位置。設農戶當前在M位置,每次移動時有三種選擇:1.移動到M-1;2.移動到M+1位置;3.移動到M*2的位置。問最少移動多少次可以移動到牛所在的位置。
分析:BFS的板子題,用隊列。用廣搜來搜索這三個狀態,直到搜索到牛所在的位置
代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#define maxn 100001
using namespace std;
int n,k;
queue<int> q;
bool vis[maxn];
int step[maxn];//記錄步數的數組
int bfs(int n,int k){
int s,temp;
q.push(n);
vis[n]=1;
while(!q.empty()){//重複使用時,用此初始化的
s=q.front();
q.pop();
for(int i=0;i<3;i++){//三個方向搜索
if(i==0)temp=s+1;
else if(i==1)temp=s-1;
else
temp=s*2;
if(temp>100000||temp<0)
continue;//越界
if(!vis[temp]){
step[temp]=step[s]+1;
if(temp==k)return step[temp];//到結束條件終止
vis[temp]=1;//置爲訪問過
q.push(temp);//temp元素放到隊列末端
}
}
}
}
int main(){
while(cin>>n>>k){
memset(vis,0,sizeof(vis));
if(n>=k)
cout<<n-k<<endl;
else
cout<<bfs(n,k)<<endl;
}
return 0;
}
4、 迷宮問題 POJ - 3984
題目
思路:
跟前面第2題很像,要更爲簡單,都是bfs找到路徑,由於輸出的是路徑不是最短路步數,在結構體中定義stepx和stepy兩個數組記錄路徑。
需要注意的是前面第2題在push一個node前只要把step置爲前一個node的step+1,這裏需要繼承前一個node的stepx和stepy,所以直接開始是定義node e=s(見下代碼)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100010;
int vis[6][6];int a[6][6];
int mp[6][6];
int base[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
struct node{
int x,y;
int stepx[30],stepy[30],cnt;
};
queue<node>q;
void bfs(){
node p;
p.x=0;p.y=0,p.cnt=0;
// vis[0][0]=1;
q.push(p);
while(!q.empty()){
node s=q.front(),tmp1;
q.pop();
if(s.x==4&&s.y==4){//到終點
printf("(0, 0)\n");
for(int i=0;i<s.cnt;++i)
printf("(%d, %d)\n",s.stepx[i],s.stepy[i]);
return;
}
//註釋的這段會稍微簡潔一些
// tmp1=s;
// for(int i=0;i<4;++i)
// {
// tmp1.x=s.x+base[i][0];
// tmp1.y=s.y+base[i][1];
// if(tmp1.x>=0&&tmp1.x<=4&&tmp1.y>=0&&tmp1.y<=4&&!vis[tmp1.x][tmp1.y]&&a[tmp1.x][tmp1.y]==0)
// {
// vis[tmp1.x][tmp1.y]=1;
// tmp1.stepx[tmp1.cnt]=tmp1.x;
// tmp1.stepy[tmp1.cnt++]=tmp1.y;
// q.push(tmp1);
// }
for(int i=0;i<4;i++){//四個方向
int xx=s.x+base[i][0];
int yy=s.y+base[i][1];
if(a[xx][yy]==0&&xx>=0&&xx<5&&yy>=0&&yy<5&&!vis[xx][yy]){
node e=s;//用中間變量結構體e來暫存,滿足要求則push,注意要先=s
e.x=xx;e.y=yy;
e.stepx[e.cnt]=e.x;
e.stepy[e.cnt++]=e.y;//注意cnt++
vis[e.x][e.y]=1;
q.push(e);
}
}
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
cin>>a[i][j];
}
}
memset(vis,0,sizeof(vis));//初始化不能忘
bfs();
return 0;
}