zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
  • 相关阅读:
    怎样简单编写一个html网页
    C# 委托实现冒泡排序
    C# 运算符
    EF 多表联查方法
    Log4net 配置文件
    vs调试 iis发布之后的项目
    继承 ,构造方法使用
    C#扩展方法
    partial 部分类
    WeakReference 弱引用
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4781902.html
Copyright © 2011-2022 走看看