[nowcoder]218-A 地、顏色、魔法
連結:https://ac.nowcoder.com/acm/contest/218/A
來源:牛客網
題目描述
紅色來源於山脈,象徵著狂躁、憤怒、混亂,血雨腥風,電光火石。
藍色來源於海島,象徵著控制、幻覺、詭計,運籌帷幄,謀定後動。
綠色來源於樹林,象徵著生命、蠻力、成長,橫衝直撞,生生不息。
黑色來源於沼澤,象徵著死亡、貪婪、腐敗,追求卓越,不計代價。
白色來源於平原,象徵著秩序、公平、正義,攜手共進,穩中求勝。
現在,你作為一名新星鵬洛客,找到了一塊絕佳的修煉地。這塊地方可以被描述成一個 n x m 的矩形。你已經在這塊地中的一些位置打好了標記。接下去,就該對整塊地賦予你的顏色了。一個位置能被賦予你的顏色,當且僅當滿足以下條件之一:
- 這個位置被打上了標記。
- 這個位置在不經過被打標記的位置的情況下與邊界不連通(這個圖是四聯通的)。換句話說,如果你從這個位置開始,在不經過被打標記的位置,且只能向上下左右四個方向移動的情況下永遠不能走到地圖的邊界,那麼這個位置符合條件。 現在,你的好基友想知道,你能為多少個位置賦予你自己的顏色呢?
輸入描述:
第一行包含兩個正整數 n, m ,表示地圖的長和寬。
接下去 n 行,每行一個長為 m 的字串,表示地圖的一行。
其中 ,表示該位置未被打標記“ . ” 表示該位置被打了標記“#”。
保證地圖僅由“ . ” 和“#”構成。
輸出描述:
輸出僅一行,包含一個整數,表示你的答案。
樣例輸入
4 4
. . . .
.###
.# .#
.###
樣例輸出
9
說明
可以被賦予顏色的位置在下圖中用@標出了。
. . . .
[email protected]@@
[email protected]@@
[email protected]@@
備註:
1 ≤ n x m ≤ 10^6
一開始我對題意的理解不知有什麼鍋鍋,認為可以掃一下外圍帶“ . ”的連通塊,然後把剩下的標成“@”結果,完美的WA掉了(20分)
#include<bits/stdc++.h> #pragma GCC optimize(2) using namespace std; int n,m; char ch[10001][10001]; int dx[5]={0,1,-1,0,0}; int dy[5]={0,0,0,1,-1}; inline void dfs(int x,int y){ ch[x][y]='*'; for(int i=1;i<=4;i++){ int sx=x+dx[i]; int sy=y+dy[i]; if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue; if(ch[sx][sy]=='.') dfs(sx,sy); } } int main(){ int ans=0; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",ch[i]+1); dfs(1,1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(ch[i][j]=='.'||ch[i][j]=='#') ch[i][j]='@'; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(ch[i][j]=='@') ans++; printf("%d",ans); return 0; }
我又讀了一遍題目,發現可以從一個點出發,從這個點向外掃連通塊,結果還是有用的,70分……
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
char ch[10001][10001];
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
inline void dfs(int x,int y){
ch[x][y]='*';cnt++;
for(int i=1;i<=4;i++){
int sx=x+dx[i];
int sy=y+dy[i];
if(sx<1||sx>n||sy<1||sy>m) {
flag=false;
return ;
}
if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue;
if(ch[sx][sy]=='.') dfs(sx,sy);
}
}
int main(){
int ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",ch[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(ch[i][j]=='#') ans++;
else if(ch[i][j]=='.'){
flag=true;
cnt=0;
dfs(i,j);
if(flag) ans+=cnt;
}
}
printf("%d",ans);
return 0;
}
當時我就在想:什麼毒瘤資料卡我點!
再讀題n*m≤10^6,這是什麼情況!肯定會炸掉啊,只能vector存圖了,只要TA超過了邊界就直接break。(80分?嗯?什麼情況?你怎麼回事?)
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
vector<char> ch[1000001];
inline void dfs(int x,int y){
ch[x][y]='*';cnt++;
for(int i=1;i<=4;i++){
int sx=x+dx[i];
int sy=y+dy[i];
if(sx<0||sx>n-1||sy<0||sy>m-1) {
flag=false;
return ;
}
if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue;
if(ch[sx][sy]=='.') dfs(sx,sy);
}
}
int main(){
int ans=0;
char str;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
scanf(" %c",&str);
ch[i].push_back(str);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(ch[i][j]=='#') ans++;
else if(ch[i][j]=='.'){
flag=true;
cnt=0;
dfs(i,j);
if(flag) ans+=cnt;
}
}
printf("%d",ans);
return 0;
}
這也太不厚道了吧……我又仔細想想,出了機組極端資料卡我那可愛的程式,發現超過邊界只能continue才能搜到更多的不符合要求的點,AC程式碼如下:
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
vector<char> ch[1000001];
inline void dfs(int x,int y){
ch[x][y]='*';cnt++;
for(int i=1;i<=4;i++){
int sx=x+dx[i];
int sy=y+dy[i];
if(sx<0||sx>n-1||sy<0||sy>m-1) {
flag=false;
continue ;
}
if(ch[sx][sy]=='#') continue;
if(ch[sx][sy]=='.') dfs(sx,sy);
}
}
int main(){
int ans=0;
char str;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
scanf(" %c",&str);
ch[i].push_back(str);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(ch[i][j]=='#') ans++;
else if(ch[i][j]=='.'){
flag=true;
cnt=0;
dfs(i,j);
if(flag) ans+=cnt;
}
}
printf("%d",ans);
return 0;
}
我還是太弱了啊,一道Dfs的大水題都讓我做個半天,繼續學習去嘍