足球 Floyd算法

足球

时间限制: 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;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81235122
今日推荐