剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
本题我写了两种解法
一:刚开始想用深度搜索,结果发现有以下4种情况用深搜是找不出来的。
加起来一共是34种,代码如下:
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
struct Point
{
int x;
int y;
}pos,pt;
int map[3][4],used[13][13][13][13][13],p[5],p1[5],book[3][4],res=0;
int x[4]={-1,0,1,0},y[4]={0,1,0,-1};
void dfs(Point pt,int n)
{
int i,a,b;
if(n==5)
{
for(i=0;i<5;i++)
p1[i]=p[i];
sort(p1,p1+5);
if(used[p1[0]][p1[1]][p1[2]][p1[3]][p1[4]])
return;
else
{
res++;
used[p1[0]][p1[1]][p1[2]][p1[3]][p1[4]]=1;
return;
}
}
for(i=0;i<4;i++)
{
a=pt.x+x[i];
b=pt.y+y[i];
if(a>=0&&a<3&&b>=0&&b<4&&book[a][b]!=1)
{
Point p1;
p1.x=a;
p1.y=b;
book[a][b]=1;
p[n]=map[a][b];
dfs(p1,n+1);
book[a][b]=0;
}
}
}
void solve()
{
int i,j;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
{
Point pt;
pt.x=i;
pt.y=j;
book[i][j]=1;
p[0]=map[i][j];
dfs(pt,1);
book[i][j]=0;
}
}
int main()
{
int i,j,k=0;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
map[i][j]=++k;
solve();
printf("%d\n",res+34);
return 0;
}
二:暴力加广搜,先找出从12个数字中挑出5中的可能,然后用广搜判断这五个点是否连通,如果连通就增加一次解法。
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
struct Point
{
int x;
int y;
};
int map[3][4],p[5],book[3][4],mark[3][4];
int x[4]={-1,0,1,0},y[4]={0,1,0,-1};
bool bfs(Point pt)
{
int i,count=0,a,b;
queue<Point>que;
que.push(pt);
while(!que.empty())
{
Point p1=que.front();
que.pop();
count++;
for(i=0;i<4;i++)
{
a=p1.x+x[i];
b=p1.y+y[i];
if(a>=0&&a<3&&b>=0&&b<4&&book[a][b]!=1&&mark[a][b]==1)
{
Point p2;
p2.x=a;
p2.y=b;
book[a][b]=1;
que.push(p2);
}
}
}
if(count==5)
return true;
else
return false;
}
bool solve()
{
int i,j,k=0;
Point pt;
memset(mark,0,sizeof(mark));
memset(book,0,sizeof(book));
for(i=0;i<3;i++)
for(j=0;j<4;j++)
{
if(map[i][j]==p[k])
{
mark[i][j]=1;
k++;
pt.x=i;
pt.y=j;
}
}
book[pt.x][pt.y]=1;
if(bfs(pt))
return true;
return false;
}
int main()
{
int a,b,c,d,e,k=1,res=0;
for(a=0;a<3;a++)
for(b=0;b<4;b++)
map[a][b]=k++;
for(a=1;a<=8;a++)
{
p[0]=a;
for(b=a+1;b<=9;b++)
{
p[1]=b;
for(c=b+1;c<=10;c++)
{
p[2]=c;
for(d=c+1;d<=11;d++)
{
p[3]=d;
for(e=d+1;e<=12;e++)
{
p[4]=e;
if(solve())
res++;
}
}
}
}
}
printf("%d\n",res);
return 0;
}