日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj2137-(GDKOI2004)城市统计【二维前缀和,bfs】

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj2137-(GDKOI2004)城市统计【二维前缀和,bfs】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


大意

有n*n的矩陣,有居民區有商業區,每個居民區曼哈頓距離最近的商業區的曼哈頓距離就是那個居民區離商業區的距離。每個格子統計一下以它為中心的2?r+1×2?r+12?r+1×2?r+1的矩陣內所有居民區離商業區的距離的和。


解題思路

先bfs計算所有居民離商業區的距離,然后用二維前綴和O(n2)O(n2)處理。

關于二維前綴和

二維前綴和就是用a[i][j]a[i][j]表示(1,1)(1,1)(i,j)(i,j)這個矩陣范圍內的和,第一行和第一列可以直接像一維那樣推,然后我們假設我們已經推出了a[i?1][j]a[i?1][j]a[i][j?1]a[i][j?1]a[i?1][j?1]a[i?1][j?1],然后我們可以看一下如果計算

我們用a[i?1][j]a[i?1][j]加上a[i][j?1]a[i][j?1],這樣的話藍色區域和紅色區域被計算過一次,可是紫色區域被累加過兩次,所以我們要減去一次紫色區間a[i?1][j?1]a[i?1][j?1]。然后在加上白色區間f[i][j]f[i][j]。
計算答案也利用容斥定理來計算。


代碼

#include<cstdio> #include<queue> #include<cstring> #define N 151 using namespace std; queue<int> x,y; const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; int n,r,f[N][N],ans[N][N],t; int c[N][N]; void bfs()//廣搜 {while (!x.empty()){for (int i=0;i<4;i++){int zx=x.front()+dx[i],zy=y.front()+dy[i];if (zx<1||zx>n||zy<1||zy>n||c[zx][zy]) continue;c[zx][zy]=true;f[zx][zy]=f[x.front()][y.front()]+1;x.push(zx);y.push(zy);//printf("%d %d\n",zx,zy);}x.pop();y.pop();} } int main() {scanf("%d",&t);while (t--){memset(f,0,sizeof(f));memset(ans,0,sizeof(ans));scanf("%d%d",&n,&r);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++){scanf("%d",&c[i][j]);if (c[i][j]) x.push(i),y.push(j);}bfs();for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1]+f[i][j];//計算前綴和for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){int wx=min(n,i+r),wy=min(n,j+r),lx=max(0,i-r-1),ly=max(0,j-r-1);//計算區域以免爆出范圍printf("%d ",ans[wx][wy]+ans[lx][ly]-ans[lx][wy]-ans[wx][ly]);//輸出答案}printf("\n");}printf("\n");} }

總結

以上是生活随笔為你收集整理的jzoj2137-(GDKOI2004)城市统计【二维前缀和,bfs】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。