题目大意:有一个N*N方阵,将其中的0替换为曼哈顿距离最近的非零元素的值;若有多余1个的最近非零元素,则维持原值0不变。
题目链接:http://poj.org/problem?id=2329
先写了一发BFS,结果TLE。写的过程中看出了一些类似DP的特质,尝试用DP写了下:两遍扫描,分别考虑来自左上和右下的元素,dp数组记录距离该元素最近的非零元素的个数、距离和位置。注意dp数组的更新规则。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stdlib.h>
#include <math.h>
using namespace std;
#define MAXN 203
#define INF 100000000
struct DPNode{
int count;
int dis;
int x;
int y;
};
int n;
int mat[MAXN][MAXN];
DPNode dp[MAXN][MAXN];
int dir[][2] = { { 0, -1 }, { 1, 0 }, { -1, 0 }, { 0, 1 } };
void UL(int i, int j)
{
if (i > 0)//L
{
if (dp[i][j].dis > dp[i - 1][j].dis + 1)
{
dp[i][j].dis = dp[i - 1][j].dis + 1;
dp[i][j].count = dp[i - 1][j].count;
dp[i][j].x = dp[i - 1][j].x;
dp[i][j].y = dp[i - 1][j].y;
}
else if (dp[i][j].dis == dp[i - 1][j].dis + 1)
{
if (!(dp[i][j].x == dp[i - 1][j].x&&dp[i][j].y == dp[i - 1][j].y
&&dp[i][j].count == 1 && dp[i - 1][j].count == 1))
dp[i][j].count += dp[i - 1][j].count;
}
}
if (j > 0)//U
{
if (dp[i][j].dis > dp[i][j - 1].dis + 1)
{
dp[i][j].dis = dp[i][j - 1].dis + 1;
dp[i][j].count = dp[i][j - 1].count;
dp[i][j].x = dp[i][j - 1].x;
dp[i][j].y = dp[i][j - 1].y;
}
else if (dp[i][j].dis == dp[i][j - 1].dis + 1)
{
if (!(dp[i][j].x == dp[i][j - 1].x&&dp[i][j].y == dp[i][j - 1].y
&&dp[i][j].count == 1 && dp[i][j - 1].count == 1))
dp[i][j].count += dp[i][j - 1].count;
}
}
}
void DR(int i, int j)
{
if (i < n - 1)//R
{
if (dp[i][j].dis > dp[i + 1][j].dis + 1)
{
dp[i][j].dis = dp[i + 1][j].dis + 1;
dp[i][j].count = dp[i + 1][j].count;
dp[i][j].x = dp[i + 1][j].x;
dp[i][j].y = dp[i + 1][j].y;
}
else if (dp[i][j].dis == dp[i + 1][j].dis + 1)
{
if (!(dp[i][j].x == dp[i + 1][j].x&&dp[i][j].y == dp[i + 1][j].y
&&dp[i][j].count == 1 && dp[i + 1][j].count == 1))
dp[i][j].count += dp[i + 1][j].count;
}
}
if (j < n - 1)//D
{
if (dp[i][j].dis > dp[i][j + 1].dis + 1)
{
dp[i][j].dis = dp[i][j + 1].dis + 1;
dp[i][j].count = dp[i][j + 1].count;
dp[i][j].x = dp[i][j + 1].x;
dp[i][j].y = dp[i][j + 1].y;
}
else if (dp[i][j].dis == dp[i][j + 1].dis + 1)
{
if (!(dp[i][j].x == dp[i][j + 1].x&&dp[i][j].y == dp[i][j + 1].y
&&dp[i][j].count == 1 && dp[i][j + 1].count == 1))
dp[i][j].count += dp[i][j + 1].count;
}
}
}
int main()
{
while (~scanf("%d", &n))
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &mat[i][j]);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[i][j].dis = INF;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (mat[i][j]>0)
{
dp[i][j].dis = 0;
dp[i][j].count = 1;
dp[i][j].x = i;
dp[i][j].y = j;
}
else
{
UL(i, j);
}
}
}
for (int i = n - 1; i >= 0; i--)
{
for (int j = n - 1; j >= 0; j--)
{
if (mat[i][j] == 0)
{
DR(i, j);
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n-1; j++)
{
printf("%d ", dp[i][j].count == 1 ? mat[dp[i][j].x][dp[i][j].y] : 0);
}
printf("%d\n", dp[i][n - 1].count == 1 ? mat[dp[i][n - 1].x][dp[i][n - 1].y] : 0);
}
}
return 0;
}