poj-2430 Lazy Cows ****

  1 //参见 http://hi.baidu.com/billdu/blog/item/6315841769e6905ff3de325e.html (有图有真相...)
2 //...
3 //
4 //dp[i][j][k]表示到达第i列,已经建设好了j个围栏,最后一列状态是k的情况下框住的最小面积
5 //
6 //另外, 我这个代码是 顺推(按黑书的分类),也就是基于当前状态,遍历之前的能得到这个当前状态的状态,取最佳值
7 //而参考的那个是 逆推, 也就是基于当前状态,计算能由这个“当前状态”推出的“下一状态”,如果这样推能使“下一状态”的值更佳
8 //则更新“下一状态”的值。
9 //
10 //另外还有一道类似的题(黑书的DP练习题:艺术馆的火灾 P121。。 ) 思路完全一样
11 // 参见 http://blog.tomtung.com/2007/05/museum-fire/ (按上面的分类,其采用的算法也属于 逆推)
12
13 #include <cstdio>
14 #include <algorithm>
15 #include <fstream>
16 #include <iostream>
17 using namespace std;
18
19 const int maxb = 15000000 + 5;
20 const int maxn = 1000 + 5;
21 const int maxk = 1000 + 5;
22 const int inf = 100000000;
23
24 //dis[i] :用于离散化,第i个有牛的列的真实列数
25 int n, k, b, dis[maxn];
26 //dp[i][j][k]; sta[i]:第i个实际列的牛的情况:1:只第一排有牛; 2:只第二排有牛; 3:两排都有牛:(与dp的k相同)
27 int dp[maxn][maxk][5], sta[maxb] = {};
28
29 struct SCow{
30 int r, c;
31 };
32 SCow cow[maxn];
33
34 //
35 int inline min(int a1, int a2, int a3 = inf, int a4 = inf, int a5 = inf){
36 int min = a1;
37 if(min > a2) min = a2;
38 if(min > a3) min = a3;
39 if(min > a4) min = a4;
40 if(min > a5) min = a5;
41
42 return min;
43 }
44
45 /*
46 //
47 int uniqueArray(int *a, int size){
48 int i = 0, j = 1;
49 while(j < size){
50 if(a[i] != a[j])
51 a[++i] = a[j];
52 j++;
53 }
54
55 return i+1;
56 }
57 */
58
59
60 //dp[i][co][1..4]的最小值
61 int inline lastMin(int i, int co){
62 if(co <= 0) return inf;
63
64 int min = inf;
65 for(int j=1; j<5; j++){
66 if(min > dp[i][co][j])
67 min = dp[i][co][j];
68 }
69 return min;
70 }
71
72
73
74 int main(){
75 scanf("%d%d%d", &n, &k, &b);
76
77 //输入
78 for(int i=0; i<n; i++){
79 scanf("%d%d", &cow[i].r, &cow[i].c);
80 dis[i] = cow[i].c; //dis
81 sta[cow[i].c] += cow[i].r; //记录牛状态
82 }
83
84 //unique dis[]
85 sort(dis, dis+n);
86 //int newSize = uniqueArray(dis, n);
87 int *a = unique(dis, dis+n);
88 int newSize = a - dis;
89
90 //初始化
91 for(int i=0; i<=k; i++)
92 for(int j=0; j<5; j++)
93 dp[0][i][j] = inf;
94 if(sta[dis[0]] == 2) dp[0][1][2] = 1;
95 else if(sta[dis[0]] == 1) dp[0][1][1] = 1;
96 dp[0][2][3] = 2;
97 dp[0][1][4] = 2;
98
99
100 //计算dp[i][j][1..4]
101 int tmpLastMin;
102 for(int i=1; i<newSize; i++){
103 for(int co=1; co<=k; co++){
104 //1
105 dp[i][co][1] = dp[i-1][co][1] + dis[i] - dis[i-1];
106 if(dp[i][co][1] > dp[i-1][co][3] + dis[i] - dis[i-1])
107 dp[i][co][1] = dp[i-1][co][3] + dis[i] - dis[i-1];
108
109 tmpLastMin = lastMin(i-1, co-1);
110 if(dp[i][co][1] > tmpLastMin + 1)
111 dp[i][co][1] = tmpLastMin + 1;
112 if(sta[dis[i]] != 1) //不能把该列的牛盖住, =inf
113 dp[i][co][1] = inf;
114
115 //2
116 dp[i][co][2] = dp[i-1][co][2] + dis[i] - dis[i-1];
117 if(dp[i][co][2] > dp[i-1][co][3] + dis[i] - dis[i-1])
118 dp[i][co][2] = dp[i-1][co][3] + dis[i] - dis[i-1];
119 if(dp[i][co][2] > tmpLastMin + 1)
120 dp[i][co][2] = tmpLastMin + 1;
121 if(sta[dis[i]] != 2) dp[i][co][2] = inf; //不能把该列的牛盖住, =inf
122
123 //3
124 dp[i][co][3] = dp[i-1][co][3] + (dis[i] - dis[i-1]) * 2; //与co的关系
125 if(co > 1){
126 if(dp[i][co][3] > dp[i-1][co-1][3] + dis[i] - dis[i-1] + 1) //与co-1的关系
127 dp[i][co][3] = dp[i-1][co-1][3] + dis[i] - dis[i-1] + 1;
128 if(dp[i][co][3] > dp[i-1][co-1][1] + dis[i] - dis[i-1] + 1)
129 dp[i][co][3] = dp[i-1][co-1][1] + dis[i] - dis[i-1] + 1;
130 if(dp[i][co][3] > dp[i-1][co-1][2] + dis[i] - dis[i-1] + 1)
131 dp[i][co][3] = dp[i-1][co-1][2] + dis[i] - dis[i-1] + 1;
132 }
133 tmpLastMin = lastMin(i-1, co-2); //与co-2的关系
134 if(dp[i][co][3] > tmpLastMin + 2)
135 dp[i][co][3] = tmpLastMin + 2;
136
137 //4
138 dp[i][co][4] = dp[i-1][co][4] + (dis[i] - dis[i-1]) * 2;
139 tmpLastMin = lastMin(i-1, co-1);
140 if(dp[i][co][4] > tmpLastMin + 2)
141 dp[i][co][4] = tmpLastMin + 2;
142 }
143 }
144
145 //结果
146 tmpLastMin = dp[newSize-1][k][3];
147 if(tmpLastMin > dp[newSize-1][k][4])
148 tmpLastMin = dp[newSize-1][k][4];
149 if(sta[dis[newSize-1]] == 2 && tmpLastMin > dp[newSize-1][k][2]){
150 tmpLastMin = dp[newSize-1][k][2];
151 }
152 else if(sta[dis[newSize-1]] == 1 && tmpLastMin > dp[newSize-1][k][1]){
153 tmpLastMin = dp[newSize-1][k][1];
154 }
155
156 printf("%d\n", tmpLastMin);
157
158
159 return 0;
160 }

posted on 2012-03-02 16:11  龙豆  阅读(731)  评论(0编辑  收藏  举报

导航