1. 程式人生 > >p1454 聖誕夜的極光

p1454 聖誕夜的極光

const and ref 因此 problem define 分享圖片 clas 才有

題目描述-->p1454 聖誕夜的極光

題意概括:

尋找聯通塊數量,這裏的連通塊定義與其他的不同.

這裏定義為曼哈頓距離不超過2的都屬於一個聯通塊.

什麽?不知道曼哈頓距離是啥?

曼哈頓距離簡易概括->|x1-x2|+|y1-y2|,兩點之間橫縱坐標的差的絕對值之和.

詳細解釋->曼哈頓距離

分析

看到大家都在說12個方向,具體是哪12個方向呢?

假設黃色點為我們當前所在節點.那我們圖中標出的紅色點,都是滿足與黃色點曼哈頓距離為2的點.

技術分享圖片

但這才有8個方向啊!

回望題意,曼哈頓距離不超過2的都屬於一個聯通塊

曼哈頓距離不超過2,那我們的圖應該是這樣的↓.

(藍色點即為與黃色點曼哈頓距離為1的.

技術分享圖片

所以說,現在12個方向就很明確了!

根據標明的坐標,我們很容易打出12個方向對應的位置變化. 像這樣↓

const int ax[]={-1,-2,1,2,0,0,0,0,1,1,-1,-1};
const int ay[]={0,0,0,0,1,2,-1,-2,1,-1,1,-1};
//const類型可自動識別數組大小.
//不過貌似不加const也可以識別

然後我們我又遇到了難題,

如何輸入?

字符類型,我們一般選擇用

scanf("%c"),getchar(),cin來進行輸入.

但是這題,用scanf,會出現蜜汁錯誤.(用scanf只get到了30pts...

而用getchar則會讀取行末換行符,需要加判斷.

所以我們直接選用cin來讀入字符.(感覺cin輸入字符還是很少出鍋的.

因此,我們搜到一個為‘#‘的位置,就去標記與它在一個聯通塊中的位置,則聯通塊個數++即可.

PS:

or ==> ||
and==> &&

---------------------代碼--------------------

#include<bits/stdc++.h>
#define IL inline
#define RI register int
IL void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s>‘9‘ or s<‘0‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘ and s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    x*=f;
}
int n,m,ans;
char res[108][108];
const int ax[]={-1,-2,1,2,0,0,0,0,1,1,-1,-1};
const int ay[]={0,0,0,0,1,2,-1,-2,1,-1,1,-1};
bool vis[108][108];
IL void dfs(int x,int y)
{
    if(vis[x][y])return;
    vis[x][y]=true;
    for(RI i=0;i<12;i++)
    {
        int nx=x+ax[i],ny=y+ay[i];
        if(nx<1 or ny<1 or nx>n or ny>m )continue;
        if(res[nx][ny]==‘#‘and !vis[nx][ny])dfs(nx,ny);
    }
}
int main()
{
    in(n),in(m);
    for(RI i=1;i<=n;i++)
        for(RI j=1;j<=m;j++)
            std::cin>>res[i][j];
    for(RI i=1;i<=n;i++)
        for(RI j=1;j<=m;j++)
        {
            if(res[i][j]==‘#‘ and !vis[i][j])
            {
                dfs(i,j);
                ans++;
            }
        }
    printf("%d",ans);
}

p1454 聖誕夜的極光