一道关于优先队列的搜索题。
我们建立一个小根堆,将开始确定的值放进去,然后进行bfs。
对于每个点,向上下左右四个方向扩展,并且更新答案,同时将没入队的节点入队即可。
最后,我们得到了一个搜索完成的图,我们判断一下合法性,输出答案即可。
这道题有一个坑点:输入可能重复同一节点但权值不同,这种情况应当判错。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 typedef long long ll; 8 int n,m; 9 ll map[1010][1010]; 10 int num,d; 11 const int mod=1000000007; 12 int dx[5]={0,0,0,1,-1}; 13 int dy[5]={0,1,-1,0,0}; 14 inline int read() { 15 int ret=0; 16 int op=1; 17 char c=getchar(); 18 while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();} 19 while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); 20 return ret*op; 21 } 22 struct node { 23 int x,y,val; 24 bool operator <(const node &x) const { 25 return val>x.val; 26 } 27 }; 28 priority_queue<node> q; 29 int vis[1010][1010]; 30 int main() { 31 freopen("flower.in","r",stdin); 32 freopen("flower.out","w",stdout); 33 n=read(); m=read(); 34 num=read(); d=read(); 35 for(int i=1;i<=n;i++) 36 for(int j=1;j<=m;j++) 37 map[i][j]=2147483646; 38 for(int i=1;i<=num;i++) { 39 int x=read(),y=read(),z=read(); 40 if(map[x][y]!=2147483646&&map[x][y]!=z) { 41 puts("Boom"); 42 return 0; 43 } 44 map[x][y]=z; 45 q.push((node){x,y,z}); 46 vis[x][y]=1; 47 } 48 while(!q.empty()) { 49 int nowx=q.top().x; 50 int nowy=q.top().y; 51 q.pop(); 52 for(int k=1;k<=4;k++) { 53 int xx=nowx+dx[k]; 54 int yy=nowy+dy[k]; 55 if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue ; 56 map[xx][yy]=min(map[xx][yy],map[nowx][nowy]+d); 57 q.push((node){xx,yy,map[xx][yy]}); 58 vis[xx][yy]=1; 59 } 60 } 61 ll ans=0; 62 for(int i=1;i<=n;i++) 63 for(int j=1;j<=m;j++) 64 ans=(ans+map[i][j])%mod; 65 for(int i=1;i<=n;i++) 66 for(int j=1;j<=m;j++) { 67 for(int k=1;k<=4;k++) { 68 int ii=i+dx[k]; 69 int jj=j+dy[k]; 70 if(ii>=1&&ii<=n&&jj<=m&&jj>=1&&map[i][j]+d<map[ii][jj]) { 71 puts("Boom"); 72 return 0; 73 } 74 if(ii>=1&&ii<=n&&jj<=m&&jj>=1&&map[i][j]-d>map[ii][jj]) { 75 puts("Boom"); 76 return 0; 77 } 78 } 79 } 80 printf("%lld",ans%mod); 81 return 0; 82 }