剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
图1.jpg
图2.jpg
图3.jpg
思路:从12各种随意抽5个,判断是否连通
#include<cstdio> #include<cstring> using namespace std; int a[3][4]={ {0,1,2,3}, {4,5,6,7}, {8,9,10,11}};//为了方便,均执行-1操作 int vec[15]; int res; int dx[4]={1,0,-1,0}; int dy[4]={0,1,0,-1}; int vis[5][5]; bool Include(int x) { for(int i=0;i<5;i++) if(vec[i]==x) return true; return false; } void Connect(int y,int x) { for(int i=0;i<4;i++) { int ny=dy[i]+y; int nx=dx[i]+x; if(0<=ny&&ny<3&&0<=nx&&nx<4&&!vis[ny][nx]&&Include(a[ny][nx])) { vis[ny][nx]=1; Connect(ny,nx); } } } void dfs(int i,int j) { if(i==12) { if(j==5) { memset(vis,0,sizeof(vis)); int y=vec[0]/4,x=vec[0]%4; vis[y][x]=1; Connect(y,x); int mark=0; for(int k=0;k<j;k++) { y=vec[k]/4; x=vec[k]%4; if(vis[y][x]==1) mark++; } if(mark==5) res++; } return ; } vec[j]=*(a[0]+i); dfs(i+1,j+1); vec[j]=0; dfs(i+1,j); } int main() { res=0; dfs(0,0); printf("%d ",res); return 0; } /* res:116 */