Poj--1944(贪心,枚举)
2014-12-10 00:23:40
思路:这题的思路很精巧,看了题解。。。感觉别人写的好飘逸,几十ms。。
自己YY了下,100多ms,不过思路还算清晰。
首先考虑,最后肯定不会是一个环(因为随便去掉一条边都能得到更优的解),对于一个需求[a,b],要么直接走a->b,要么1->a , b->n->1,从起点走过去。
由于至少有一个断点,而且我们发现如果存在一个断点,那么对于每个需求,它的连接方向就确定了(总有一个方向的走法被断点截断),所以就可以通过枚举断点的位置来确定出每个需求的走法,然后用贪心扫一遍最少需要的边。用 d[i] = j 来表示 i 这个点最远需要连到 j。
1 /************************************************************************* 2 > File Name: 1944.cpp 3 > Author: Natureal 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 09 Dec 2014 11:05:58 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 10010; 27 28 int N,P,d[maxn]; 29 struct node{ 30 int l,r; 31 }t[maxn]; 32 33 bool cmp(node a,node b){ 34 if(a.l == b.l) 35 return a.r < b.r; 36 return a.l < b.l; 37 } 38 39 int main(){ 40 scanf("%d%d",&N,&P); 41 for(int i = 1; i <= P; ++i){ 42 scanf("%d%d",&t[i].l,&t[i].r); 43 if(t[i].l > t[i].r) 44 swap(t[i].l,t[i].r); 45 } 46 sort(t + 1,t + P + 1,cmp); 47 int ans = INF; 48 for(int k = 1; k <= N; ++k){ 49 //枚举断点,断在[i-1,i]这条边上。 50 memset(d,0,sizeof(d)); 51 int pos = 0,res = 0; 52 for(int i = 1; i <= P; ++i){ 53 if(t[i].l < k && k <= t[i].r){ 54 d[1] = max(d[1],t[i].l); 55 d[t[i].r] = N; 56 res = 1; 57 } 58 else{ 59 d[t[i].l] = max(d[t[i].l],t[i].r); 60 } 61 } 62 for(int i = 0; i <= N; ++i){ 63 if(i > pos) pos = i; 64 if(d[i] > pos){ 65 res += d[i] - pos; 66 pos = d[i]; 67 } 68 } 69 ans = min(ans,res); 70 } 71 printf("%d\n",ans); 72 return 0; 73 }