剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
这道题首先想到的是从12个数里随机抽取5个数的不重复组合有多少种,再利用深度优先搜索去判断这些组合中哪些符合要求
public class Email {
static int count=0;
static int sum=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[]=new int[13];
int b[][]=new int[4][5];
for(int i=1;i<=12;i++)
a[i]=i;
int b_vis[][]=new int[4][5];
int v[]=new int[13];//记录状态
int v_s[]=new int[15];//记录所选得数
int k=1;
int s[]=new int[15];//用于存5个数
for(int i=1;i<=3;i++)
for(int j=1;j<=4;j++)
{
b[i][j]=k++;
}
f(b,s,v,v_s,b_vis,1);
System.out.print(sum);
}
public static void dfs(int b[][],int v_s[],int b_vis[][],int x,int y)
{
int l[][]= {{1,0},{0,1},{-1,0},{0,-1}};
int xx,yy;
for(int i=0;i<4;i++)
{
xx=x+l[i][0];
yy=y+l[i][1];
if(xx>=1 && xx<=3 && yy>=1 && yy<=4 && b_vis[xx][yy]==0)
{
if(v_s[b[xx][yy]]==1)
{
count++;
b_vis[xx][yy]=1;
dfs(b,v_s,b_vis,xx,yy);
}
}
}
}
public static void check(int b[][],int s[],int v_s[],int b_vis[][])
{
for(int i=0;i<15;i++)
v_s[i]=0;
for(int i=0;i<=3;i++)
for(int j=0;j<=4;j++)
b_vis[i][j]=0;
for(int i=1;i<=5;i++)
{
v_s[s[i]]=1;
}
for(int x=1;x<=12;x++)
{
int i=(x-1)/4+1;
int j=(x-1)%4+1;
if(v_s[b[i][j]]==1)
{
count=1;
b_vis[i][j]=1;
System.out.println(i+" "+j);
dfs(b,v_s,b_vis,i,j);
break;
}
}
if(count==5)
sum++;
}
public static void f(int b[][],int s[],int v[],int v_s[],int b_vis[][],int p)
{
if(p==6)
{
check(b,s,v_s,b_vis);
return;
}
for(int i=s[p-1]+1;i<=12;i++)//从十二个数中抽取5个不重复的数
{
if(v[i]==0)
{
v[i]=1;
s[p]=i;
f(b,s,v,v_s,b_vis,p+1);
v[i]=0;
}
}
}
}