【题目】
剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
【思路】
首先考虑剪任意五张邮票的问题,再考虑剪下来的这五张邮票是否连通。
①全排列:剪下任意五张邮票的所有可能;
1 int stamp[12]={0,0,0,0,0,0,0,1,1,1,1,1};//一共12张邮票,有五张要减下来 2 int main(){ 3 int key=0; 4 do{ 5 if(check(stamp)) key++; 6 }while(next_permutation(stamp,stamp+12));//生成不同的全排列 7 cout<<key; 8 }
②编写check函数,判断五张邮票是不是连通的。首先要将1维数组转成二维数组。
1 bool check(int stamp[12]){ 2 int t[3][4]; 3 int p=0; 4 for(int i=0;i<3;i++){ 5 for(int j=0;j<4;j++){ 6 t[i][j]=stamp[p++]; 7 } 8 } 9 int cnt=0; 10 for(int i=0;i<3;i++){ 11 for(int j=0;j<4;j++){ 12 if(t[i][j]==1){//看要减下来的五张邮票能不能一遍走过 13 dfs(t,i,j); 14 cnt++; 15 } 16 } 17 } 18 return cnt==1; 19 }
③dfs算法
1 void dfs(int g[3][4],int i,int j){ 2 g[i][j]=0;//已经走过标记为0 3 if(i-1>=0&&g[i-1][j]==1) dfs(g,i-1,j); 4 if(i+1<=2&&g[i+1][j]==1) dfs(g,i+1,j); 5 if(j-1>=0&&g[i][j-1]==1) dfs(g,i,j-1); 6 if(j+1<=3&&g[i][j+1]==1) dfs(g,i,j+1); 7 }
完整代码(答案116)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int stamp[12]={0,0,0,0,0,0,0,1,1,1,1,1};//一共12张邮票,有五张要减下来 4 5 void dfs(int g[3][4],int i,int j){ 6 g[i][j]=0;//已经走过标记为0 7 if(i-1>=0&&g[i-1][j]==1) dfs(g,i-1,j); 8 if(i+1<=2&&g[i+1][j]==1) dfs(g,i+1,j); 9 if(j-1>=0&&g[i][j-1]==1) dfs(g,i,j-1); 10 if(j+1<=3&&g[i][j+1]==1) dfs(g,i,j+1); 11 } 12 13 bool check(int stamp[12]){ 14 int t[3][4]; 15 int p=0; 16 for(int i=0;i<3;i++){ 17 for(int j=0;j<4;j++){ 18 t[i][j]=stamp[p++]; 19 } 20 } 21 int cnt=0; 22 for(int i=0;i<3;i++){ 23 for(int j=0;j<4;j++){ 24 if(t[i][j]==1){//看要减下来的五张邮票能不能一遍走过 25 dfs(t,i,j); 26 cnt++; 27 } 28 } 29 } 30 return cnt==1; 31 } 32 33 int main(){ 34 int key=0; 35 do{ 36 if(check(stamp)) key++; 37 }while(next_permutation(stamp,stamp+12));//生成不同的全排列 38 cout<<key; 39 }