題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3359
題目大意:給你一個h*w的矩陣B,矩陣B是由矩陣A經過變化得到的,對於矩陣B內的某一個元素等於加上所有滿足的再除以的對數。現在要你求出原來的矩陣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;
}