HiHoCoder [Offer收割]编程练习赛6 C. 图像算子(高斯消元小数版)

传送门

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

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

果。

假设原图为 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

解题思路:

其实将这个题目转化一下的话 就是一个高斯消元的问题,首先我们按照题目意思列出

(W?D+1)?(H?D+1) 个方程,包含 D?D 个未知数的方程,然后通过高斯消元

模板,就可以搞定了。

具体的说一下怎么构造的这些方程组,就拿样例来说吧:

A:   113819961219181351517191060185315121817

因为 D 矩阵的长度是 3 ,所以 B 矩阵的的规模是 (5?3+1) ?(5?3+1) 的,嗯哼,那么

就是相当于 A 矩阵的每个子矩阵中的数分别乘以 D 矩阵的数,这个其实说不太明白 最好是在纸上

画一画基本上就出来了,分别对应相乘完之后,得到 (H?D+1)?(W?D+1) 个方程和

D?D 个未知数,在这里需要注意的是,构造的增广矩阵是 double 的,解也是 double 的。具体还是 看我的代码吧。

My Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;

typedef long long LL;
const double eps = 1e-7;
const int MAXN = 1e4+5;
int equ, var;///equ个方程 var个变量
double a[MAXN][100];///增广矩阵
double x[MAXN];///解的数目
void Gauss()
{
    int Max_r;///当前列绝对值最大的存在的行
    ///col:处理当前的列
    int row = 0;
    int free_x_num;
    int free_index;
    for(int col=0; row<equ&&col<var; row++,col++)
    {
        Max_r = row;
        for(int i=row+1; i<equ; i++)
            if(fabs(a[i][col]) > fabs(a[Max_r][col]))
                Max_r = i;

        if(Max_r != row)
            for(int i=0; i<var+1; i++)
                swap(a[row][i], a[Max_r][i]);
        for(int i=row+1; i<equ; i++)
        {
            double f = a[i][row]/a[row][col];
            for(int j=col; j<var+1; j++)
                a[i][j] -= f*a[row][j];
        }
    }
    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];
    }
}
double aa[70][70];
int main()
{
    int H, W, D;
    while(~scanf("%d%d%d",&H,&W,&D))
    {
        for(int i=0; i<H; i++)
            for(int j=0; j<W; j++)
                scanf("%lf",&aa[i][j]);
        memset(a, 0, sizeof(a));
        memset(x, 0, sizeof(x));
        equ = (H-D+1)*(W-D+1);
        var = D*D;
        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] = aa[i/(W-D+1)+j/D][i%(W-D+1)+j%D];
        Gauss();
        for(int i=0; i<D*D; i++)
        {
            int k = floor(x[i]+0.5);
            if(i%D == D-1)
                printf("%d\n",k);
            else
                printf("%d ",k);
        }
    }
    return 0;
}
时间: 2024-10-05 03:10:15

HiHoCoder [Offer收割]编程练习赛6 C. 图像算子(高斯消元小数版)的相关文章

hihocoder - [Offer收割]编程练习赛17

hihocoder - [Offer收割]编程练习赛17 题目1 : F1 Score 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和他的小伙伴们一起写了很多代码.时间一久有些代码究竟是不是自己写的,小Hi也分辨不出来了. 于是他实现了一个分类算法,希望用机器学习实现自动分类. 为了评价这个分类算法的优劣,他选出了N份有标记的代码作测试集,并决定用F1 Score作为评价标准. 给出N份代码的实际作者是不是小Hi以及分类算法预测的结果,请你计算F1 Sco

hihocoder [Offer收割]编程练习赛18 C 最美和弦(dp)

题目链接:http://hihocoder.com/problemset/problem/1532 题解:一道基础的dp,设dp[i][j][k][l]表示处理到第几个数,当前是哪个和弦错了几次初始x值是多少.这里还要再辅助一个val[k]表示处理到当前情况只错了k次的最小值是多少因为改变的不止是和弦还有初始值,可以看一下代码理解一下. #include <iostream> #include <cstring> #include <cstdio> #include &

hihoCoder [Offer收割]编程练习赛3 D子矩阵求和

子矩阵求和 http://hihocoder.com/discuss/question/3005 声明一下: n是和x一起的,m是和y一起的 x是横着的,y是纵着的,x往右为正,y往下为正 (非常反常规的定义) 性质好题 看起来无从下手. 两个关键性质: 证明挺显然的.画画图 同余方程exgcd即可 子矩阵和? 先算出(0,0)的,每次平移,加减一行一列前n或m个, 细节: 1.纵向要循环到n,横向循环到m 2.注意开long long 3.反常规的设定真讨厌 #include<bits/std

hihocoder [Offer收割]编程练习赛14 小Hi和小Ho的礼物

题目1 : 小Hi和小Ho的礼物 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 某人有N袋金币,其中第i袋内金币的数量是Ai.现在他决定选出2袋金币送给小Hi,再选2袋金币送给小Ho,同时使得小Hi和小Ho得到的金币总数相等.他想知道一共有多少种不同的选择方法. 具体来说,有多少种下标四元组(i, j, p, q)满足i, j, p, q两两不同,并且i < j, p < q, Ai + Aj = Ap + Aq. 例如对于数组A=[1, 1, 2, 2, 2]

hihocoder [Offer收割]编程练习赛14 投掷硬币

题目2 : 投掷硬币 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一枚神奇的硬币.已知第i次投掷这枚硬币时,正面向上的概率是Pi. 现在小Hi想知道如果总共投掷N次,其中恰好M次正面向上的概率是多少. 输入 第一行包含两个整数N和M. 第二行包含N个实数P1, P2, ... PN. 对于30%的数据,1 <= N <= 20 对于100%的数据,1 <= N <= 1000, 0 <= M <= N, 0 <= Pi &

hihocoder [Offer收割]编程练习赛14 可疑的记录

题目3 : 可疑的记录 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一棵N个节点的树,编号1-N,其中1号节点是整棵树的根.他把这棵树的N-1条边记录成N-1行,每行2个整数a和b,表示a是b的父节点. 喜欢恶作剧的小Ho在小Hi的记录里加了一行两个整数,于是小Hi不得设法找出这行可疑的记录.具体来说,如果去掉某一行之后,余下N-1行按小Hi的规则(a是b的父节点)恰好能构成一棵N个节点的树,并且满足编号恰好是1-N且1号节点是根,那么被去掉的一行就被视

hihocoder [Offer收割]编程练习赛14 剑刃风暴

题目4 : 剑刃风暴 时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 主宰尤涅若拥有一招非常厉害的招式——剑刃风暴,“无论是战士还是法师,都害怕尤涅若的武士刀剑技”. 现在战场上有N名敌对英雄,他们的位置分别为(Xi, Yi),而剑刃风暴的伤害范围是一个半径为R的圆形,尤涅若可以选择一个坐标作为剑刃风暴的中心,所有处于这个圆形范围内的英雄都会受到剑刃风暴的伤害. 现在尤涅若想要知道,他的剑刃风暴最多可以同时伤害到多少敌对英雄. 输入 第一行为两个整数N和R,分别敌对

hihocoder offer收割编程练习赛13 D 骑士游历

思路: 矩阵快速幂. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 using namespace std; 5 6 typedef long long ll; 7 typedef vector<ll> vec; 8 typedef vector<vec> mat; 9 10 const ll mod = 1e9 + 7; 11 12 ll n, x, y;

hihocoder [Offer收割]编程练习赛4

描述 最近天气炎热,小Ho天天宅在家里叫外卖.他常吃的一家餐馆一共有N道菜品,价格分别是A1, A2, ... AN元.并且如果消费总计满X元,还能享受优惠.小Ho是一个不薅羊毛不舒服斯基的人,他希望选择若干道不同的菜品,使得总价在不低于X元的同时尽量低. 你能算出这一餐小Ho最少消费多少元吗? 输入 第一行包含两个整数N和X,(1 <= N <= 20, 1 <= X <= 100) 第二行包含N个整数A1, A2, ..., AN.(1 <= Ai <= 100)