USACO Milking Cow

  天下午无聊,花了1个多小时,做了下USACO中MilkCow这题。初看这题感觉似乎挺难的,求的是最值,莫非用DP?仔细想下,发现并不涉及什么高深的算法,解决这题的关键在于编程的相关技巧。

     按人类的思维,解决这题非常简单,就是合并各个时段,求取极值即可。那么按计算机该怎么做呢?很简单也是这几步,只是把人类合并集合的步骤展开来罢了(计算机可没这么聪明。。。)

  讨论程序首先要看的是数据结构,它关系着算法的效率以及对算法的理解。我这里用的是很简单的数据结构---low和high这两个数组,他们分别存储各个时段的下限和上限值。具体的步骤如下:

  1 对各个集合按下限值进行排序(上限值作为卫星数据),这里用的是插入排序,因为感觉数据量不是很大(5000个数据),还有就是很有可能大部分都是排好序的数据,用快排可能会退化。

  2 合并各集合,这里用到了两个指针i、j,分别指向待合并的集合以及将要被合并的集合,为了节省存储空间,我这里把被合并掉的集合的low和high的相应项都设为0,方便在解决求最值的问题。

  3 求取最值,这里比较简单就不赘述了。

     简单的思想就是如此,这也是这题官方答案的第一种思路,好了,上代码:

 

Milking Cow
   
     
1 /*
2 ID: happyan3
3 PROG: milk2
4 LANG: C++
5   */
6
7 #include < iostream >
8 #include < fstream >
9 #include < cassert >
10
11   using namespace std;
12
13   int N;
14 unsigned int * low = NULL;
15 unsigned int * high = NULL;
16
17   void sort( void ); // use insertion sort
18   void Merge( void );
19 unsigned int FindLongestMilked( void );
20 unsigned int FindLongestNoMilked( void );
21
22   int main( void )
23 {
24 ifstream milk2In;
25 milk2In.open( " milk2.in " );
26
27 milk2In >> N;
28
29 low = new unsigned int [N];
30 high = new unsigned int [N];
31
32 for ( int i = 0 ; i < N; i ++ )
33 {
34 milk2In >> low[i] >> high[i];
35 }
36
37 sort();
38 Merge();
39
40 int nLongestMilked = FindLongestMilked();
41 int nLongestNoMilked = FindLongestNoMilked();
42
43 ofstream milk2Out;
44 milk2Out.open( " milk2.out " );
45
46 milk2Out << nLongestMilked << " " << nLongestNoMilked << endl;
47
48 delete [] low;
49 delete [] high;
50 milk2In.close();
51 milk2Out.close();
52 return 0 ;
53 }
54   void sort( void )
55 {
56 int keyLow = 0 ;
57 int keyHigh = 0 ;
58 int i = 0 ;
59 for ( int j = 1 ; j < N; j ++ )
60 {
61 keyLow = low[j];
62 keyHigh = high[j];
63
64 i = j - 1 ;
65 while (i >= 0 && low[i] > keyLow)
66 {
67 low[i + 1 ] = low[i];
68 high[i + 1 ] = high[i];
69 i = i - 1 ;
70 }
71 low[i + 1 ] = keyLow;
72 high[i + 1 ] = keyHigh;
73 }
74 }
75
76
77   void Merge( void )
78 {
79 int i = 0 ;
80 int j = 1 ;
81 while (i < N && j < N)
82 {
83 if (high[i] < low[j]) // 无法合并
84   {
85 i = j;
86 j ++ ;
87 }
88 else
89 {
90 if (high[i] >= high[j]) // 可全部包含在内
91   {
92 low[j] = 0 ; // 设置标志表示已被合并
93   high[j] = 0 ;
94 }
95 else // 原上限小于被合并时段上限,求并集
96 {
97 high[i] = high[j];
98 low[j] = 0 ;
99 high[j] = 0 ;
100 }
101 j ++ ;
102 }
103 }
104
105 }
106
107
108
109
110 unsigned int FindLongestMilked( void )
111 {
112 unsigned int res = 0 ;
113
114 int interval = 0 ;
115 for ( int i = 0 ; i < N; i ++ )
116 {
117 interval = high[i] - low[i];
118 if (res < interval)
119 res = interval;
120 }
121
122 return res;
123 }
124
125
126 unsigned int FindLongestNoMilked( void )
127 {
128 unsigned int res = 0 ;
129
130 int interval = 0 ;
131
132 int i = 0 ;
133 int j = 1 ;
134 while (i < N && j < N)
135 {
136 if ( 0 == high[i])
137 {
138 i = j;
139 j ++ ;
140 }
141 else
142 {
143 if ( 0 == low[j])
144 {
145 j ++ ;
146 }
147 else // 两者都不为0
148 {
149 interval = low[j] - high[i];
150 if (res < interval)
151 res = interval;
152 i = j;
153 j ++ ;
154 }
155 }
156 }
157
158 return res;
159 }
160

 

你可能感兴趣的:(USACO)