• POJ 1161 Walls【floyd 以面为点建图】


    题目链接:http://poj.org/problem?id=1161

    题目大意:

    1.给出m个区域,n个俱乐部点。接下来是n个俱乐部点以及各个区域由什么点围成。求一个区域到各个俱乐部点的距离之和最小。

    解题思路:

    1.这题建图比较麻烦,以区域为点建图,区域之间若有边,则两区域的距离为1,建完图后跑一遍floyd就可以求出两两区域的最小距离。

    2.对于答案,枚举每一个区域到各个俱乐部点的相邻区域的距离之和,取最小值。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #define mem(a, b) memset(a, b, sizeof(a))
     5 using namespace std;
     6 const int inf = 0x3f3f3f3f;
     7 
     8 int m, n, l;
     9 int club[35], vis[260][210];//标记i点是否与j区域相邻 
    10 int edge[260][260]; //更新i到j边的相邻区域是哪个
    11 int map[260][260]; //建图 
    12 
    13 void floyd()
    14 {
    15     for(int i = 1; i <= m; i ++)
    16         map[i][i] = 0;
    17     for(int k = 1; k <= m; k ++)
    18         for(int i = 1; i <= m; i ++)
    19             for(int j = 1; j <= m; j ++)
    20                 map[i][j] = map[j][i] = min(map[i][j], map[i][k] + map[k][j]);
    21 }
    22 
    23 int main()
    24 {
    25     while(scanf("%d", &m) != EOF) //m个区域 
    26     {
    27         mem(edge, -1); //表示没有相邻区域 
    28         mem(map, inf), mem(vis, -1);
    29         scanf("%d%d", &n, &l);//n个点,其中l个点是俱乐部所在的点 
    30         for(int i = 1; i <= l; i ++)
    31             scanf("%d", &club[i]);
    32         for(int i = 1; i <= m; i ++)
    33         {
    34             int k, temp;
    35             scanf("%d", &k); //每个区域由k个点逆时针围成 注意最后一个点与第一个点也有边 
    36             scanf("%d", &temp);
    37             vis[temp][i] = 1;
    38             int first = temp;
    39             for(int j = 1; j < k; j ++)
    40             {
    41                 int x;
    42                 scanf("%d", &x);
    43                 vis[x][i] = 1;
    44                 if(edge[temp][x] == -1 || edge[x][temp] == -1)
    45                     edge[temp][x] = edge[x][temp] = i;
    46                 else
    47                 {
    48                     map[edge[temp][x]][i] = map[i][edge[temp][x]] = 1;
    49                     edge[temp][x] = edge[x][temp] = i;
    50                 }
    51                 temp = x;
    52             }
    53             if(edge[first][temp] == -1 || edge[temp][first] == -1)
    54                 edge[first][temp] = edge[temp][first] = i;
    55             else
    56             {
    57                 map[edge[first][temp]][i] = map[i][edge[first][temp]] = 1;
    58                 edge[first][temp] = edge[temp][first] = i;
    59             }
    60         }
    61         floyd();
    62         int ans = inf;
    63         for(int i = 1; i <= m; i ++) //枚举答案 枚举每一个区域 
    64         {
    65             int temp = 0;
    66             for(int j = 1; j <= l; j ++)
    67             {
    68                 int temp1 = inf;
    69                 for(int k = 1; k <= m; k ++)
    70                 {
    71                     if(vis[club[j]][k] == -1)
    72                         continue;
    73                     temp1 = min(temp1, map[i][k]);
    74                 }
    75                 temp += temp1;
    76             }
    77             ans = min(ans, temp);
    78         }
    79         printf("%d
    ", ans);
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    备份的数据库存儲過程
    用反射调用任意.net库中的方法
    基于.NET的多线程编程入门
    手写分页函数C#
    .net中的泛型
    prototype.js开发笔记
    此方法用于确认用户输入的不是恶意信息
    利用DataSet、DataTable、DataView按照自定义条件过滤数据
    读取文件列表
    注册客户端脚本
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11650181.html
Copyright © 2020-2023  润新知