题意:给出一个n*n的矩阵,非零的位置不变输出,对于0的位置如果最近的非零位置只有一个则输出那个最近非零值,否则输出0本身。Aij , Apq距离的定义为 |i − p| + |j − q|.
解法:搞了一发dp,从左上到右下,从右下到左上各扫一遍。n^2复杂度,提交后64ms,排到了C++里的第5,估计大家好多用了搜索,表示搜索自己不懂搞这题。
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
using namespace std;
int num[210][210];
int n;
struct point
{
int number;
int mindis;
};
struct help
{
int x,y;
bool operator==(help a)
{
return a.x==x&&a.y==y;
}
} ans[210][210];
point rem1[210][210];
void make(int i,int j,int k,int h)
{
if(rem1[i][j].mindis==rem1[k][h].mindis+1)
{
if(rem1[i][j].number==1&&rem1[k][h].number==1&&ans[i][j]==ans[k][h])
return;
rem1[i][j].number+=rem1[k][h].number;
}
else if(rem1[i][j].mindis>rem1[k][h].mindis+1)
{
rem1[i][j].mindis=rem1[k][h].mindis+1;
rem1[i][j].number=rem1[k][h].number;
ans[i][j]=ans[k][h];
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
rem1[i][j].mindis=1000;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",num[i]+j);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(num[i][j]>0){
rem1[i][j].mindis=0;
rem1[i][j].number=1;
ans[i][j].x=i;
ans[i][j].y=j;
}
else
{
make(i,j,i-1,j);
make(i,j,i,j-1);
}
for(int i=n;i>=1;i--)
for(int j=n;j>=1;j--)
if(num[i][j]>0){
rem1[i][j].mindis=0;
rem1[i][j].number=1;
ans[i][j].x=i;
ans[i][j].y=j;
}
else
{
make(i,j,i+1,j);
make(i,j,i,j+1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<n;j++)
if(rem1[i][j].number==1)
printf("%d ",num[ans[i][j].x][ans[i][j].y]);
else
printf("0 ");
if(rem1[i][n].number==1)
printf("%d\n",num[ans[i][n].x][ans[i][n].y]);
else
printf("0\n");
}
return 0;
}