剪邮票
如图1, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,图2,图3中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
图1 图2 图3
思路:1、首先从12数中选出5个数(求其所有组合数) 用dfs(保证五个数是递增的,避免重复) ,存入一维数组a中
2、将a中的这五个数转化为二维坐标形式,然后将其在地图上置1(将vis置1),再用bfs判断地图上这5个置1的数是否相连
1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 #include<cstring> 5 6 using namespace std; 7 8 int a[100]; 9 int vis[4][5]; //下标为0的不用 10 int dx[] = { 1,-1,0,0 }; 11 int dy[] = { 0,0,1,-1 }; 12 13 int result = 0; 14 15 struct node 16 { 17 int x, y; 18 }s; 19 20 void bfs(int a[]) 21 { 22 memset(vis, 0, sizeof(vis)); //记得将vis置零,防止有残余的1 23 int x, y; 24 25 //把一维下标转换为二维坐标 26 for (int i = 1; i <= 5; ++i) 27 { 28 if (a[i] % 4 == 0) 29 { 30 x = a[i] / 4; 31 y = 4; 32 } 33 else 34 { 35 x = a[i] / 4 + 1; 36 y = a[i] % 4; 37 } 38 vis[x][y] = 1; 39 } 40 41 s.x = x; 42 s.y = y; 43 44 queue<node>Q; 45 Q.push(s); 46 vis[s.x][s.y] = 0; 47 int num = 1; 48 49 node t; 50 while (!Q.empty()) 51 { 52 t = Q.front(); 53 Q.pop(); 54 55 for (int i = 0; i < 4; ++i) 56 { 57 int xx = t.x + dx[i]; 58 int yy = t.y + dy[i]; 59 if (xx >= 1 && xx <= 3 && yy >= 1 && yy <= 4 && vis[xx][yy] == 1) 60 { 61 ++num; //每有一个相连,num就自增 62 vis[xx][yy] = 0; 63 s.x = xx; 64 s.y = yy; 65 Q.push(s); 66 } 67 } 68 } 69 70 if (num == 5) //如果这5个数都相连 71 { 72 ++result; 73 } 74 75 } 76 77 void dfs(int step) //从12个数中取出5个(即12取5的所有组合),存入一维数组a中(从下标1开始存储) 78 { 79 if (step == 6) 80 { 81 bfs(a); //用bfs判断取出的这5个数在图中是否相连 82 return; 83 } 84 85 for (int i = 1; i <= 12; ++i) 86 { 87 if (i > a[step - 1]) //以递增的顺序选出,可以防止重复 88 { 89 a[step] = i; 90 dfs(step + 1); 91 } 92 } 93 94 95 } 96 97 int main() 98 { 99 memset(a, 0, sizeof(a)); 100 dfs(1); 101 cout << result << endl; 102 103 return 0; 104 }