hihocoder图像算子(高斯消元)

描述

在图像处理的技术中,经常会用到算子与图像进行卷积运算,从而达到平滑图像或是查找边界的效果。

假设原图为H × W的矩阵A,算子矩阵为D × D的矩阵Op,则处理后的矩阵B大小为(H-D+1) × (W-D+1)。其中:

B[i][j] = ∑(A[i-1+dx][j-1+dy]*Op[dx][dy]) | (dx = 1 .. D, dy = 1 .. D), 1 ≤ i ≤ H-D+1, 1 ≤ j ≤ W-D+1

给定矩阵A和B,以及算子矩阵的边长D。你能求出算子矩阵中每个元素的值吗?

输入

第1行:3个整数,H, W, D,分别表示原图的高度和宽度,以及算子矩阵的大小。5≤H,W≤60,1≤D≤5,D一定是奇数。

第2..H+1行:每行W个整数,第i+1行第j列表示A[i][j],0≤A[i][j]≤255

接下来H-D+1行:每行W-D+1个整数,表示B[i][j],B[i][j]在int范围内,可能为负数。

 

输入保证有唯一解,并且解矩阵的每个元素都是整数。

输出

第1..D行:每行D个整数,第i行第j列表示Op[i][j]。

样例输入
5 5 3
1 6 13 10 3
13 1 5 6 15
8 2 15 0 12
19 19 17 18 18
9 18 19 5 17
22 15 6
35 -36 51
-20 3 -32
样例输出
0 1 0
1 -4 1
0 1 0


高斯消元的思路如下
1、找到一个基准行,这一行左起第一个非零元素应该是 列元素中最大的
2、用该基准行去把位于该行下面的所有的列(最大列元素所在的列)化成0,最后会变成一个上三角阵
3、从最后一行开始往上求解

# include <cstdio>
# include <cmath>
# include <cstring>
# include <algorithm>

using namespace std;

const int MAXN = 1e4 + 5;
int equ, var;
double a[MAXN][100];
double x[MAXN];
double A[70][70];

void guass() {

    for (int i = 0; i < equ; i++) {
        int maxRow = i;
        double maxV = fabs(a[i][i]);
        for (int j = i + 1; j < equ; j++) {
            if (maxV < fabs(a[j][i])) {
                maxV = fabs(a[j][i]);
                maxRow = j;
            }
        }

        // 交换
        for (int j = i; j <= var; j++) {
            swap(a[i][j], a[maxRow][j]);
        }

        // 化成下三角
        for (int j = i + 1; j < equ; j++) {
            double c = a[j][i] / a[i][i];
            a[j][i] = 0;
            for (int k = i + 1; k <= var; k++) {
                a[j][k] -= c * a[i][k];
            }
        }
    }

    /*
    for (int i = equ - 1; i >= 0; i--) {
        x[i] = a[i][var] / a[i][i];
        for (int j = i - 1; j >= 0; j--) {
            a[j][var] -= x[i] * a[j][i];
        }
    }
    */
    for(int i=equ-1; i>=0; i--)
    {
        double tmp = a[i][var];
        for(int j=i+1; j<var; j++)
            tmp -= a[i][j]*x[j];
        x[i] = tmp/a[i][i];
    }
}

int main() {

    int H, W, D;
    while(scanf("%d%d%d", &H, &W, &D) != EOF) {
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                scanf("%lf",  &A[i][j]);
            }
        }
        var = D * D;
        equ = (H - D + 1)  * (W - D + 1);
        memset(a, 0, sizeof(a));
        memset(x, 0, sizeof(x));
        for (int i = 0; i < equ; i++) {
            scanf("%lf", &a[i][var]);
        }

        for (int i = 0; i < equ; i++) {
            for (int j = 0; j < var; j++) {
                a[i][j] = A[i / (W - D + 1) + j / D][i % (W - D + 1) + j % D];
            }
        }
        /*
        for (int i = 0; i < equ; i++) {
            for (int j = 0; j < var; j++) {
                printf("%lf ", a[i][j]);
            }
            printf("\n");
        }
        */
        guass();

        for (int i = 0; i < var; i++) {
            int k = floor(x[i] + 0.5);
            if (i % D == D - 1) {
                printf("%d\n", k);
            } else {
                printf("%d ", k);
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/zhaopAC/p/8638277.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值