1. 程式人生 > >poj 1161 Walls

poj 1161 Walls

pro 建圖 space 是把 算法 http namespace algorithm clas

https://vjudge.net/problem/POJ-1161

題意:
有m個區域,n個小鎮,有c個人在這些小鎮中,他們要去某一個區域中聚會,從一個區域到另一個區域需要穿墻,問這些人聚到一起最少需要穿過幾道墻。
題中給出的區域是用小鎮描述的,某幾個小鎮圍成一個區域,每一個區域按照順時針方向給出的。
思路:
首先用兩個vector,一個描述一個區域,屬性是這個區域的邊界有哪些點,另一個描述一個點,屬性是這些點屬於哪個區域。然後接下來,我們把每一個區域看成一個點,開始建圖。
這題的難點就在於怎麽建圖,首先我們把一個區域看成一個點,那麽怎麽才能知道兩個區域相鄰呢?由於描述每個區域的點是以順時針方向給出的,所以對於每個區域,當我們把每個區域的店push_back完之後,再把這個區域的點push_back進去,那麽就相當於這些點構成了一個環,對於相鄰的兩點,如果說vis[點j][點j+1]沒有東西的話,那麽這個的值就等於這個區域,如果有值的話,那麽就說明保存的值與當前的區域是相鄰的,就把距離賦值為1,澤陽就把建圖的問題解決了。
之後就是求任意兩個區域的最短距離,用到了floyd算法,這倒是一個新姿勢,不過很簡單,就是把兩點之間的距離通過圖上的每一個點松弛。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int inf = 0x3f3f3f3f;
 8 
 9 vector<int> r[400],t[400];
10 int club[40];
11 int g[400][400];
12 int vis[400][400];
13 
14 int main()
15 {
16     int m,n,c;
17 18 memset(r,0,sizeof(r)); 19 memset(t,0,sizeof(t)); 20 21 scanf("%d%d%d",&m,&n,&c); 22 23 memset(g,inf,sizeof(g)); 24 25 for (int i = 1;i <= 399;i++) g[i][i] = 0; 26 27 for (int i = 0;i < c;i++) scanf("%d",&club[i]); 28 29 for (int i = 1;i <= m;i++)
30 { 31 int o; 32 33 scanf("%d",&o); 34 35 for (int j = 0;j < o;j++) 36 { 37 int oo; 38 39 scanf("%d",&oo); 40 41 r[i].push_back(oo); 42 43 t[oo].push_back(i); 44 } 45 46 r[i].push_back(r[i][0]); 47 } 48 49 for (int i = 1;i <= m;i++) 50 { 51 for (int j = 0;j < r[i].size() - 1;j++) 52 { 53 int fr = r[i][j],to = r[i][j+1]; 54 55 if (vis[fr][to]) g[vis[fr][to]][i] = g[i][vis[fr][to]] = 1; 56 else vis[fr][to] = vis[to][fr] = i; 57 } 58 } 59 60 61 62 for (int i = 1;i <= m;i++) 63 for (int j = 1;j <= m;j++) 64 for (int k = 1;k <= m;k++) 65 { 66 if (g[j][k] > g[j][i] + g[i][k]) 67 g[j][k] = g[j][i] + g[i][k]; 68 } 69 70 int ans = inf; 71 72 for (int i = 1;i <= m;i++) 73 { 74 int sum = 0; 75 76 for (int j = 0;j < c;j++) 77 { 78 int minn = inf; 79 80 int cc = club[j]; 81 82 for (int k = 0;k < t[cc].size();k++) 83 { 84 int w = t[cc][k]; 85 86 minn = min(minn,g[w][i]); 87 } 88 89 sum += minn; 90 } 91 92 ans = min(ans,sum); 93 } 94 95 printf("%d\n",ans); 96 97 return 0; 98 }

poj 1161 Walls