NOI科目校 資訊學知識點測評-圖論專題【51nod】 遊記
比賽地址:Link
A 顏色塊
1.0 秒 131,072.0 KB 100 分
一張 \(m\times n\) 的圖片,每個點有一個顏色,相同顏色的點連在一起(上下左右四連通)屬於同一個顏色塊,問這張圖片共有多少個顏色塊。資料保證單個顏色塊的點數量不超過 \(10^5\)。
輸入
第一行:2個數\(n\),\(m\),中間用空格分隔,表示地圖的大小(\(1 <= m, n <= 1000\))。
後面\(n\)行:每行\(m\)個字元,對應圖片中的點的顏色編號\(c\)。(\(0 <= c <= 9\))。
輸出
輸出一個數,對應顏色塊的數量
資料範圍
\(1 <= m, n <= 1000\)
輸入樣例
5 5
11122
33112
31113
22113
21111
輸出樣例
5
樣例解釋
整個圖中,有1個顏色為1的色塊,2個顏色為2的色塊,2個顏色為3的色塊,因此共有5個色塊。
通過記錄
唰唰唰!秒殺!
毫無任何問題。
程式碼
#include<bits/stdc++.h> using namespace std; int mp[1005][1005];//存地圖 bool v[1005][1005];//visited int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//四個方向 int m,n,ans=0;//ans=顏色塊個數 void dfs(int x,int y){ v[x][y]=1;//設定為標記過 for(int i=0;i<4;i++){ int dx=dir[i][0]+x,dy=dir[i][1]+y; if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!v[dx][dy]&&mp[dx][dy]==mp[x][y]) dfs(dx,dy);//符合條件 } } int main(){ char c; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>c; mp[i][j]=c-'0';//過於緊湊 } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(!v[i][j]){//每個都找一遍 dfs(i,j); ans++; } } } cout<<ans<<endl; return 0; }
B 冬奧會之積水問題
3.0 秒 131,072.0 KB 100 分
冬奧會賽場旁有一片正方形的窪地(長寬都為\(n\)),地形凹凸不平,窪地的四周是一圈排水池。有一天,下了很大的雨,窪地形成了積水,告訴你窪地的地形(\(n\times n\)塊的高度),由你來計算,窪地的積水量。
例如:\(n = 4\)
3 4 5 6
4 1 2 7
5 1 2 8
6 7 8 9
因為四周都是排水池(邊界上的水會通過排水池流走),最終只有橘色部分(內圈):
1 2
1 2
能夠形成積水,積水高度由他們4周(綠色部分,外圈)的最低高度決定,這個高度是4(左上角0,0位置的3雖然小於4,但2個高度為4的方塊已經形成了封閉的一圈),所以總的積水量是10。
輸入
第一行:一個數n,表示窪地的大小(\(3 <= n <= 1000\))
後面n行:每行n個數,表示地形的高度h[i,j](\(0 <= h[i,j] <= 1000000\))。
輸出
輸出總的積水量。
輸入樣例
4
3 4 5 6
4 1 2 7
5 1 2 8
6 7 8 9
輸出樣例
10
思路
floodfill。
模擬海平面,每次增高都嘗試流一遍。
悲慘de做題過程
最開始寫了一發,慘拿46TAT
結果發現數組開小了/kx
然後卡在91卡了0.5h,終於發現寫的時候沒有處理0,順序反了/kx
然後就100了/cy
這告訴了我們:一定要搞清楚you在幹什麼!!!!!
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int mp[1005][1005];//地圖
char vis[1005][1005];//是的,其實沒啥用
struct three{
int gao,x,y;//gao是高度
bool operator <(three b) const{
return gao>b.gao;
}
};
priority_queue<three> q;
int n,m,mx=-1;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
signed main(){
cin>>n;
m=n;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){cin>>mp[i][j];mx=max(mx,mp[i][j]);}//mx存最大值
for(int i=1;i<=m;i++){//處理四周
q.push({mp[1][i],1,i});
q.push({mp[n][i],n,i});
vis[1][i]=2;
vis[n][i]=2;
}
for(int i=1;i<=n;i++){
q.push({mp[i][1],i,1});
q.push({mp[i][m],i,m});
vis[i][1]=2;
vis[i][m]=2;
}
int ans=0,hpm=0;//hpm=海平面
three now;
while(!q.empty()&&hpm<=mx){
//cout<<q.top().gao<<' '<<hpm<<endl;
now=q.top();
while(!q.empty()&&now.gao<=hpm){
if(vis[now.x][now.y]==1){//這地方被淹了
ans+=hpm-now.gao;
//cout<<now.x<<","<<now.y<<":"<<now.gao<<" "<<hpm<<endl;
}
q.pop();
vis[now.x][now.y]=2;
for(int i=0;i<4;i++){
int dx=now.x+dir[i][0];
int dy=now.y+dir[i][1];
if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!vis[dx][dy]){//檢視四周
vis[dx][dy]=1;
q.push({mp[dx][dy],dx,dy});
}
}
now=q.top();
}
hpm++;
}
cout<<ans<<endl;
return 0;
}
/*以下是自造測試資料
4
0 2 100 0
10000 1 1 233
114 1 1 514
0 123 456 0
10
0 0 0 0 1 1 1 0 0 0
0 0 1 1 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 0 0 0
*/
(C沒做出來不放了)
D 黏菌網路
1.0 秒 131,072.0 KB 100 分
小明正在研究黏菌(slime molds)。他有一張網狀格柵,共\(10\times10\)個交點,每個交點上可以放置一些物體。他選擇了其中3個交點,分別放置黏菌(M),糖(S),以及一塊有毒物質(P),如下所示:
..........
..........
..........
..S.......
..........
.....P....
..........
..........
.....M....
..........
之後觀察黏菌是否能避開毒物,並沿網格以最短路線找到糖。
小明希望你先幫忙算出黏菌到達糖之前至少要經過多少個空交點,以便他做實驗記錄。
輸入
輸入共10行,每行一個長度為10的字串描述\(10\times10\)格柵中交點的情況。其中'.'表示空交點,'M'表示放置了黏菌,'S'表示放置了糖,'P'表示放置了毒物。保證輸入資料中僅存在一組'M','S','P'。
輸出
輸出一個整數,表示黏菌經過的空交點的最小數量。
輸入樣例
..........
..........
..........
..S.......
..........
.....P....
..........
..........
.....M....
..........
輸出樣例
7
樣例解釋
..........
..........
..........
..S.......
..7.......
..6..P....
..5.......
..4.......
..321M....
..........
如上所示,黏菌需要經過至少7個空交點。
思路
這題放在T4也是絕了,是四道題裡最簡單的。
一個障礙,\(10\times 10\)大小,也不過如此。
直接爆搜。
通過記錄
直接寫。
code
#include<bits/stdc++.h>
using namespace std;
int n=10,sx,sy,ex,ey,ans=0;//startx,starty,endx,endy
bool mp[15][15];//map
bool v[15][15];//visited
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct th{//three
int x,y,stp;
}now;
queue<th> q;
int bfs(){//bfs
q.push({sx,sy,0});
v[sx][sy]=1;
while(!q.empty()){
now=q.front();
if(now.x==ex&&now.y==ey) return now.stp-1;//end
q.pop();
for(int i=0;i<4;i++){
int dx=dir[i][0]+now.x,dy=dir[i][1]+now.y;
if(dx>=1&&dx<=n&&dy>=1&&dy<=n&&!mp[dx][dy]&&!v[dx][dy]){//ok
v[dx][dy]=1;
q.push({dx,dy,now.stp+1});
}
}
}
return -1;
}
int main(){
char c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>c;
if(c=='M') sx=i,sy=j;//m
else if(c=='S') ex=i,ey=j;//s
else if(c=='P') mp[i][j]=1;//p
}
cout<<bfs()<<endl;
return 0;
}