足球
时间限制: 1 Sec 内存限制: 128 MB
题目描述
yoyo得到了一个足球,这个足球与其他的足球一样,表面有 12 个正五边形和 20 个正六边形组成,足球的每个面初始的时候都为白色。现在yoyo把这个足球拆解开来,32个面编号为1~32。爱画画的yoyo希望将足球的某些面涂为黑色(可能是 0 个),在每次涂色操作中,慢慢只可以将某一些相邻或者联通的面一起涂为黑色(两个面相邻当且仅当他们共用一条边)。例如,yoyo可以在一次涂色操作中将面 1、2、3、4、5 涂为黑色,但是他不可以将面11 和 24 涂为白色,因为面 11 和 24 是不相邻也不联通的。求yoyo所需要的最少的涂色次数。
输入
第一行包含一个整数 t,表示有t组测试数据,对于每组测试数据:
输入包含一行,该行包含 32 个整数,每个数的值等于 0 时表示白色,等于 1 时表示黑色。
输出
对于每组测试数据,输出Case c: ans,其中 c 为测试数据编号,ans 为最少的操作次数。
样例输入
3
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5
1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
样例输入
Case 1: 1
Case 2: 0
Case 3: 2
Case 1: 1
Case 2: 2
Case 3: 2
Case 4: 1
Case 5: 14
提示
除了相邻的数面也相邻外,面 1 和面 13 是相邻的,面 13 和面 17 是相邻的,面 17 和面 32 是相邻的,
面 15 和面 32 是相邻的,面 19 和面 32 是相邻的。
PS:1和32不相邻。
题解
先把所有相邻的点赋值为1,再用Floyd算法把所有点之间的最短距离打表求出来。
之后每输入一组样例,则对样例中的1进行dfs深搜,然后深搜把所有相邻为1且值为1的点重新赋值为0。
最后记录下主循环中dfs的次数即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 32 + 1;//最多32个点
int dis[maxn][maxn];//记录两点之间的最短距离
int vis[maxn];
void init(){
memset(dis,0x3f3f3f3f,sizeof(dis));//初始化
dis[32][32] = 0;
for(int i = 1; i < maxn - 1; i++){
dis[i][i] = 0;//相同两点的距离为0
dis[i][i + 1] = 1;//相邻两点之间的距离为1
dis[i + 1][i] = 1;//相邻两点之间的距离为1
}
//相邻两点之间的距离为1
dis[1][13] = dis[13][1] = 1;
dis[17][13] = dis[13][17] = 1;
dis[17][32] = dis[32][17] = 1;
dis[15][32] = dis[32][15] = 1;
dis[19][32] = dis[32][19] = 1;
//Floyd算法,区间动态规划
for(int k = 1; k < maxn; k++)//枚举断点
for(int i = 1; i < maxn; i++)
for(int j = 1; j < maxn; j++)
if(dis[i][j] > dis[i][k]+dis[k][j])
dis[i][j] = dis[i][k]+dis[k][j];
}
void dfs(int x){
vis[x] = 0;//标记已经访问过
for(int i = 1; i < maxn; i++){
if(vis[i]&&dis[x][i]==1)
dfs(i);
}
}
int main(){
init();
int t;
cin>>t;
for(int u = 1;u <= t;u++){
for(int i = 1;i < maxn; i++)
cin>>vis[i];
int ans = 0;
for(int i = 1; i < maxn; i++){
if(vis[i]){
ans++;
dfs(i);
}
}
cout<<"Case "<<u<<": "<<ans<<endl;
}
return 0;
}