分析
听说是水题,但还是没想出来。
$ dp[i] $为$ [1,i] $的需要的喷头数量。
那么$ dp[i]=min(dp[j])+1 $其中$ j<i $
这是个$ O(n^2)$的东西,用单调队列优化一下就行了
复杂度$ O(L) $
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=250;
int A[maxn][maxn], num[maxn*maxn], id[1000005], cnt, ok[maxn][maxn], n;
int now[maxn][maxn], ans[maxn][maxn], can[maxn][maxn], vis[maxn][maxn];
int dx[4]={0,0,1,-1}, dy[4]={1,-1,0,0};
struct Node{ int x,y,dis,numm; };
bool in(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=n; }
queue<Node> que;
void bfs(int x,int y,int dis,int numm){
que.push((Node){x,y,dis,numm});
while(!que.empty()){
Node a=que.front(); que.pop();
x=a.x; y=a.y; dis=a.dis++; numm=a.numm;
for(int i=0;i<4;i++){
int px=x+dx[i], py=y+dy[i];
if(!in(px,py) || vis[px][py] || ok[px][py]) continue;
vis[px][py]=1; a.x=px; a.y=py;
if(dis< now[px][py]){ans[px][py]=numm;can[px][py]=0;now[px][py]=dis;}
if(dis==now[px][py]){can[px][py]++;}
que.push(a);
}
}
}
int main(){
int t; scanf("%d",&t);
while(t--){
cnt=0; memset(id,0,sizeof(id)); memset(num,0,sizeof(num)); memset(ok,0,sizeof(ok));
memset(ans,0,sizeof(ans)); memset(can,0,sizeof(can));
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%d",&A[i][j]);
if(A[i][j]) id[A[i][j]]=++cnt, num[cnt]=A[i][j], ok[i][j]=1;
}
memset(now,127,sizeof(now));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(!ok[i][j]) continue;
vis[i][j]=1; bfs(i,j,1,id[A[i][j]]);
memset(vis,0,sizeof(vis));
}
for(int i=1;i<=n;i++){
for(int j=1;j<n;j++){
if(!ok[i][j] && can[i][j]==1) printf("%d ",num[ans[i][j]]);
else printf("%d ",A[i][j]);
}
if(!ok[i][n] && can[i][n]==1) printf("%d\n",num[ans[i][n]]);
else printf("%d\n",A[i][n]);
}
if(t!=0) puts("");
}
return 0;
}