标题:剪邮票
(仅仅连接一个角不算相连)
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
如【图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;
}