poj 1009 Edge Detection (未完成)

本文介绍了一种算法,用于求解图像中每个像素与其周围8个像素差值的绝对值最大值。该算法适用于图像处理领域,通过对输入数据进行预处理并利用巧妙的数据结构减少重复计算,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题意:求各像素与周围8个像素差的绝对值的最大值。

参考:http://blog.youkuaiyun.com/thestoryofsnow/article/details/6257857


没弄明白。。改天再来看吧。。


208K   16MS

#include <stdio.h>
 
int n, t, k;
int num[2000], sum[2000], digit[2000], ansdigit[5000], ansnum[5000];
//求绝对值函数,可以用math中的同名函数
int abs(int x)
{
  if (x < 0) return -x;
  return x;
}
//循环变量i和周围元素位置映射
/*****
*0 1 2
*3   4
*5 6 7
******/
inline int map(int c, int now)
{
  switch (c)
  {
    case 0: return now - t - 1;
    case 1: return now - t;
    case 2: return now - t + 1;
    case 3: return now - 1;
    case 4: return now + 1;
    case 5: return now + t - 1;
    case 6: return now + t;
    case 7: return now + t + 1;
  }
}
//算出位置y的元素值,这里forward很巧妙,为0向前找,为1向后找
int number(int c, int y, bool forward)
{
  int i;
  if (forward)
  {
    for (i = c; i <= n; ++i)
      if (sum[i] >= y) break;
    return i;
  }
  else
  {
    for (i = c; i > 0; --i)
      if (sum[i] < y) break;
    return i+1;
  }
}
//判断边界情况 
bool ok(int now, int i)
{
  if (now < t && (i == 1 || i == 0 || i == 2)) return false;//起始行的前一行
  if (now > sum[n] - t && (i == 6 || i == 5 || i == 7)) return false;//结束行的后一行
  if (now % t == 1 && (i == 0 || i == 3 || i == 5)) return false;//左边一行的左边
  if (now % t == 0 && (i == 2 || i == 4 || i == 7)) return false;//右边一行的右边
  return true;
}
//比较与周围8个元素之差的绝对值大小
int get(int x, int now)
{
  int i, max = 0, m;
  for (i = 0; i < 8; ++i)
  {
    m = map(i, now);
    if (ok(now, i) && m > 0 && m <= sum[n])
    {
      m = number(x, m, i / 4);
      if (max < abs(digit[x] - digit[m])) max = abs(digit[x] - digit[m]);
    }
  }
  return max;
}
//减少重复计算 
int late(int x, int now, int r)
{
    int p;
    if (r <= now) return 1;
    if (now % t != 1)
    {
        if (digit[number(x, now - 1, 0)] != digit[x]) return 1;
        if (now > t)
        {
            p = number(x, now - t - 1, 0);
            if ((sum[p] - 1) / t < (now - 1) / t)
            {
              if (sum[p] <= now - t + 1) return 1;
              if (r > sum[p] - 1 + t) r = sum[p] - 1 + t;
            }
        }
        if (now <= sum[n] - t)
        {
            p = number(x, now + t - 1, 1);
            if ((sum[p] - 1) / t == (now - 1) / t + 1)
            {
              if (sum[p] <= now + t + 1) return 1;
              if (r > sum[p] - 1 - t) r = sum[p] - 1 - t;
            }
        }
        return r - now + 1;
    }
    else
    {
        if (now > t)
        {
            p = number(x, now - t, 0);
            if ((sum[p] - 1) / t < (now - 1) / t)
            {
              if (sum[p] <= now - t + 1) return 1;
              if (r > sum[p] - 1 + t) r = sum[p] - 1 + t;
            }
        }
        if (now <= sum[n] - t)
        {
            p = number(x, now + t, 1);
            if ((sum[p] - 1) / t == (now - 1) / t + 1)
            {
              if (sum[p] <= now + t + 1) return 1;
              if (r > sum[p] - 1 - t) r = sum[p] - 1 - t;
            }
        }
        return r - now + 1;
    }
}
//程序的主体部分,计算start和end之间的部分。这段程序实际上是个递归,多行的情况可以归约到start和end在同一行的情况
void make(int x, int start, int end)
{
  int i, r;
  int a = (start - 1) / t, b = (end - 1) / t;
  if (a != b)//如果不在同一行
  {
    make(x, start, b * t);//归约
    make(x, b * t + 1, end);//同一行的情况
    return;
  }
  //通过get函数算出最大的绝对值,保存在last中,the保存当前位置算出的最大绝对值。如果两者相同,就要进行合并
  int last = get(x, start), sum = 0, the;
  for (i = start; i <= end;)
  {
    the = get(x, i);
    r = late(x, i, end - 1);
    if (the == last)
      sum += r;//合并
    else
    {
      ansdigit[++k] = last;
      ansnum[k] = sum;
      sum = r;
      last = the;
    }
    i += r;
  }
  ansdigit[++k] = last;
  ansnum[k] = sum;
}
int main()
{
  int i, x, y;
  sum[0] = 0;
  while (scanf("%d", &t) && t)
  {
    i = 0;
    k = 0;
    while (scanf("%d%d", &x, &y) && (x || y))
    {
      digit[++i] = x; //digit数组保存输入元素
      num[i] = y;//num数组保存元素个数
      sum[i] = sum[i - 1] + num[i];//sum数组记录元素个数和,主要用于判断元素i的周围8个元素是什么
    }
    n = i;
    for (i = 1; i <= n; ++i)
    {
      if (num[i] <= t + t + 2)//不存在同一个元素跨越3行的情况
        make(i, sum[i - 1] + 1, sum[i]);
      else
      {
        make(i, sum[i - 1] + 1, sum[i - 1] + t + 1);//前面部分同if部分
        ansdigit[++k] = 0;//中间直接为0
        ansnum[k] = num[i] - 2 * t - 2;//0的个数
        make(i, sum[i] - t, sum[i]);//后面部分也需要计算
      }
    }
    printf("%d/n", t);//输出开始
    for (i = 1; i <= k;)
    {
      int outdigit = ansdigit[i];
      int outnum = 0;
      while (i <= k && ansdigit[i] == outdigit)//如果相邻元素相同,需要合并
        outnum += ansnum[i++];
      printf("%d %d/n", outdigit, outnum);
    }
    printf("0 0/n");
  }
  printf("0/n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值