poj1009 Edge Detection

给一个n * m的矩阵(n * m ≤ 1e9, m ≤ 1e9)A, 求矩阵A'。

定义A'(i, j) = max(abs(A(i, j) - A(u, v))), 其中(u, v)在矩阵内同时在以(i, j)为中心的九宫格范围内。

考虑到矩阵大小,当然不是按照传统方式呈现矩阵,而是用一种流程编码(RLE)的编码方式表示。

编码方式题目已经交代的很清楚了。

看似很棘手的一个题目,对于如此大的数据量感觉似乎无从下手。

注意到题目说明pair数不会超过1e3。

也就是说,相连的重复数字是很多的,这是本题能够被解决的先决条件。

我们定义A(i, j)的位置是(i * width + j)(i, j从0开始)。

我们定义当前pair(i)的最小位置为f(i)。

如果能够知道A'中所有pair的f值,答案即可得到。

然而准确找到所有pair的位置(不重不漏)是困难的,但是找到它们出现的可能位置(允许冗余)则是可行的。

我们断言:A'中所有pair的f值对应的位置(简记为突变位置)若不在某一行的开端,则必在以A中某个突变位置为中心的九宫格范围内。

画图易证。

当突变位置在某一行的起点时候需要特判。

并非所有行都需要特判,只需要在每个pair前两行和后两行进行特判即可,因为中间行周围的元素都和它本身相同。

复杂度落到可控范围内。

这样我们找到所有伪命中点最后再处理一下(去重)就行了,具体实现见代码。

 

 

http://poj.org/problem?id=1009

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1e3 + 10;
 8 
 9 struct Point{
10     int v, len;
11     Point(int v = 0, int len = 0) : v(v), len(len) {}
12 };
13 
14 Point P[maxn], Q[maxn * 30];
15 int p[maxn];
16 int k1, k2;
17 int L, N;
18 
19 bool inRange(int x, int y) { return x < N / L && x >= 0 && y >= 0 && y < L; }
20 
21 bool cmp(Point a, Point b) { return a.len < b.len; }
22 
23 int f(int x, int y){
24     int pos = x * L + y + 1;
25     int l = -1, r = k1 - 1;
26     while(r - l > 1){
27         int mid = (r + l) >> 1;
28         if(p[mid] >= pos) r = mid;
29         else l = mid;
30     }
31     return P[r].v;
32 }
33 
34 int F(int x, int y){
35     int ans = -1;
36     for(int i = -1; i < 2; i++){
37         for(int j = -1; j < 2; j++){
38             int nx = x + i, ny = y + j;
39             if(!inRange(nx, ny)) continue;
40             ans = max(ans, abs(f(nx, ny) - f(x, y)));
41         }
42     }
43     return ans;
44 }
45 
46 int Process(int x, int y, int pos){
47     for(int i = -1; i < 2; i++){
48         for(int j = -1; j < 2; j++){
49             int pos1 = pos + i * L + j;
50             int nx = x + i, ny = y + j;
51             if(!inRange(nx, ny)) continue;
52             Q[k2++] = Point(F(nx, ny), pos1);
53         }
54     }
55 }
56 
57 void solve(){
58     k2 = 0;
59     int pos = 0;
60     p[0] = P[0].len;
61     for(int i = 1; i < k1; i++) p[i] = p[i - 1] + P[i].len;
62     for(int i = 0; i < k1; i++){
63         int x = pos / L, y = pos % L;
64         int nex = pos + P[i].len;
65         int nexrow = (nex - 1) / L;
66         Process(x, y, pos);
67         if(y) Process(x, 0, x * L);
68         if(x != nexrow) Process(nexrow, 0, nexrow * L);
69         pos += P[i].len;
70     }
71     sort(Q, Q + k2, cmp);
72     Q[k2].len = N;
73     for(int i = 0; i < k2; i++){
74         int j = i;
75         while(i + 1 < k2 && Q[i].v == Q[i + 1].v) ++i;
76         printf("%d %d\n", Q[i].v, Q[i + 1].len - Q[j].len);
77     }
78 }
79 
80 int main(){
81     //freopen("in.txt", "r", stdin);
82     //freopen("out.txt", "w", stdout);
83     while(~scanf("%d", &L) && L){
84         N = 0;
85         printf("%d\n", L);
86         for(int i = 0; ; i++){
87             scanf("%d%d", &P[i].v, &P[i].len);
88             N += P[i].len;
89             if(!(P[i].v || P[i].len)){
90                 k1 = i;
91                 break;
92             }
93         }
94         solve();
95         puts("0 0");
96     }
97     puts("0");
98     return 0;
99 }
View Code

 

posted @ 2015-09-04 16:26  astoninfer  阅读(254)  评论(0编辑  收藏  举报