标题:剪邮票
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
看到很多用搜索的,想了想,并查集也能做,相邻也就是连在一起了。
先用一个结构体记录每个格子的编号、坐标、是否被选,然后选出五个格子,计算这五个格子有多少个独立分块,如果只有一个,说明是连着的,属于一种方案。
代码:
#include<bits/stdc++.h> using namespace std; int pre[12]; struct youpiap { int x, y, flag; }p[12]; int find(int x) { if(x == pre[x]) return x; return pre[x] = find(pre[x]); } void join(int n) { int xx = p[n].x, yy = p[n].y; int father = find(n); for(int i = 0; i < 12; i++) { if(i == n || p[i].flag == 0) continue; if((p[i].x==xx&&p[i].y==yy+1) || (p[i].x==xx&&p[i].y==yy-1) || (p[i].x==xx+1&&p[i].y==yy) || (p[i].x==xx-1&&p[i].y==yy)) { pre[find(i)] = father; } } } int main() { int sum = 0; for(int i = 0; i < 12; i++) { pre[i] = i; p[i].flag = 0; } int kk = 0; for(int i = 1; i <= 3; i++) for(int j = 1; j <= 4; j++) { p[kk].x = i; p[kk].y = j; kk++; } for(int i = 0; i < 8; i++) { for(int j = i+1; j < 9; j++) { for(int k = j+1; k < 10; k++) { for(int q = k+1; q < 11; q++) { for(int t = q+1; t < 12; t++) { p[i].flag = 1, p[j].flag = 1, p[k].flag = 1, p[q].flag = 1, p[t].flag = 1; for(int i = 0; i < 12; i++) if(p[i].flag) join(i); set<int> s; for(int i = 0; i < 12; i++) if(p[i].flag) s.insert(find(i)); if(s.size() == 1) sum++; for(int tt = 0; tt < 12; tt++) pre[tt] = tt; p[i].flag = 0, p[j].flag = 0, p[k].flag = 0, p[q].flag = 0, p[t].flag = 0; } } } } } cout << sum << endl; return 0; }