剪郵票dfs+bfs+組合+結構體
#include<iostream>
#include<queue>
using namespace std;
struct Point
{
int x;
int y;
};
queue<Point>que;
int sum=0;
int a[3][4]={0};//代表取了哪幾個數
int visited[13]={0};//用於dfs抽取任意5張數字不同的郵票
int mark[3][4]={0};//用於bfs判斷相連的郵票是否被抽取到
int x[4]={-1,0,1,0},y[4]={0,1,0,-1}; //坐標套路,用於4次for循壞進行上下左右
int bfs_mark[3][4]={0};
int h[5]={0};//記錄取出的5個郵票
int xx,yy;//記錄第一個郵票的位置,方便入棧
int bfs();//前置聲明
void dfs(int x)//任意選取5個,且數字從大到小
{
if(x==5) //剪完5個時
{
Point p1; p1.x=xx; p1.y=yy; //保證每次取出5張郵票都能始第一個進行入隊判斷;
que.push(p1);
int is_connect=bfs();//判斷5個是否相連
if(is_connect)
sum++;
return;
}
else
for(int i=0;i<3;i++) //有坐標的題目最好用坐標且記錄
for(int j=0;j<4;j++)
if(visited[a[i][j]]==0) //可以取
{
if(x==0) //記錄郵票的開端
{
xx=i;yy=j;h[0]=a[i][j];
}
if(a[i][j]>h[x-1]) //保證取出的郵票數值遞增
{
h[x]=a[i][j];
visited[a[i][j]]=1;
mark[i][j]=1; //(i,j)處郵票已在5張之中
dfs(x+1);//當一個程序運行報錯的時候,很有可能為邏輯思想錯誤,如dfs(x++),又調用了本身
visited[a[i][j]]=0;
mark[i][j]=0;
h[x]=0;
}
}
}
int bfs()//操作選出的郵票,判斷是否相連
{
int i,count=0,a,b;
while(!que.empty())
{
Point p1=que.front(); //每次判斷都以隊列的頭(數字最小的郵票5個的第一個)進行bfs 相當於dfs的起點,dfs(0)
int xx=p1.x;
int yy=p1.y;
que.pop();
count++;
bfs_mark[xx][yy]=1;//已經bfs了 使得已被記錄count的數據不被再次bfs,防止二次入隊
for(i=0;i<4;i++) //與dfs的for循環類似,這個for循環是bfs的核心,也就是當處於某個點時,它所出現的情況
{
a=p1.x+x[i];
b=p1.y+y[i];
if(a>=0&&a<3&&b>=0&&b<4&&mark[a][b]==1&&bfs_mark[a][b]==0)
{
Point p2;
p2.x=a;
p2.y=b;
bfs_mark[a][b]=1;//無論進隊還是出隊,只要遍歷過,就代表已經bfs了,不能再次
que.push(p2);
}
}
}
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
bfs_mark[i][j]=0;//reset
if(count==5)
{
for(int i=0;i<5;i++)
cout<<h[i];
if(i=4) cout<<endl;
return 1;
}
else
return 0;
}
int main()
{ int s=0;
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
a[i][j]=++s;
dfs(0);//剪第一張
cout<<sum;
return 0;
}
剪郵票dfs+bfs+組合+結構體