HDU-3359 Kind of a Blur (高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3359

题目大意:给你一个h*w的矩阵B,矩阵B是由矩阵A经过变化得到的,对于矩阵B内的某一个元素B[i][j]等于A[i][j]加上所有满足abs(i-p)+abs(j-q)<=dA[p][q]再除以(p,q)的对数。现在要你求出原来的矩阵A的值。

题目思路:不得不吐槽下这个题。。。坑点是真的多,首先是鬼畜的输出格式,接着就是这个题输入w和h是反着的。。先输入列,再输入行。。。还有就是题目说了当 h == 0 && w == 0 && d == 0时才退出,可实际上只要 h == 0 && w == 0就退出了。。因为这个wa到怀疑人生。。。

言归正传,说下这个题目的做法。这个题也算是比较常规的高斯消元的题目了,将每个格子的值列出一个曼哈顿距离小于d的元素相加的方程,最后可以构成一个(h*w) * (h*w)的矩阵,再借助高斯消元解决就行了。

具体实现看代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
typedef vector<int> VI;
const int inf = 0x3f3f3f3f;

const double exps = 1e-8;

int h, w, d;
int to[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
bool vis[15][15];
double A[200][200], a[200];
int dcmp(double x) {
	if (fabs(x) < exps) return 0;
	return x < 0 ? -1 : 1;
}
void guass(int m, int n) {
	for (int i = 0; i < m; i++) {
		int pv = i, id;
		for (int j = 0; j <= n; j++) {
			for (int k = i + 1; k < m; k++) {
				if (fabs(A[k][j]) > fabs(A[pv][j])) {
					pv = k;
				}
			}
			if (dcmp(A[pv][j])) break;
		}
		swap(A[i], A[pv]);
		for (id = 0; id <= n && !dcmp(A[i][id]); id++);
		if (id > n) return;
		for (int j = i + 1; j < m; j++) {
			if (!dcmp(A[j][id])) continue;
			double f = A[j][id] / A[i][id];
			for (int k = id + 1; k <= n; k++) A[j][k] -= A[i][k] * f;
			A[j][id] = 0;
		}
	}
}
/*-1 无解,0 多组解,1 唯一解*/
int solve(int m, int n) {
	guass(m, n);
	int r1 = 0, r2 = 0;
	for (int i = 0; i < m; i++) {
		bool sign = true;
		for (int j = 0; j <= n; j++) {
			if (dcmp(A[i][j])) {
				r2++;
				if (j < n) r1++;
				sign = false;
				break;
			}
		}
		if (sign) break;
	}
	if (r1 != r2) return -1;
	if (r1 == r2 && r1 != n) return 0;
	for (int i = n - 1; i >= 0; i--) {
		A[i][n] /= A[i][i];
		for (int j = i - 1; j >= 0; j--) A[j][n] -= A[i][n] * A[j][i];
	}
	return 1;
}
int get_dis(int xa, int ya, int xb, int yb) {
	return abs(xa - xb) + abs(ya - yb);
}

int main() {
	//FIN;
	int flag = 0;
	while (~scanf("%d%d%d", &w, &h, &d)) {
		if (w == 0 || h == 0) break;
		if (flag) puts("");
		flag = 1;
		int N = w * h;
		clr(A);
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				int x = i * w + j;
				scanf("%lf", &a[x]);
				int cnt = 0;
				for (int p = 0; p < h; p++) {
					for (int q = 0; q < w; q++) {
						if (get_dis(i, j, p, q) <= d) {
							cnt++;
							int now = p * w + q;
							A[now][x] = 1;
						}
					}
				}
				A[x][N] = 1.0 * a[x] * cnt;
			}
		}
		solve(N, N);
		for (int i = 0; i < N; i++) {
			printf("%8.2f", A[i][N]);
			if ((i + 1) % w == 0) printf("\n");
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/82466488
今日推荐