B組group1:A - Artwork

qq_45712954發表於2020-09-27

題目連結:https://vjudge.net/contest/397282#problem/A
題解:一個人能否從左下角到達右上角,而不經過圓形連線的區域。
演算法是儲存左下角的點,逐個判斷與他相鄰的點,如果能4夠到達右上角,那麼該人到達不了右上角,注意每次路徑都需要重置。
程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct p
{
    int rr;//橫座標
    int cc;//縱座標
    int ra;//半徑
};
int rc[1100];//儲存橫座標
p P[1100];//儲存點
int r,c;//代表長和寬
int n;//點的個數
int fl,fl2;//判斷橫縱座標是否到邊界
int f[1100];//標記是否被用過
int cou=0;//儲存個數
void dfs(int i)//序數
{
    if(fl2==1)//判斷是否能從左下角到達右上角
        return ;
    if(P[i].cc<=P[i].ra||P[i].ra+P[i].rr>=r)
    {
        fl2=1;
        return ;
    }
    for(int j=0; j<n; j++)
    {
        if(f[j]==0)//沒用過
        {
            if((P[i].rr-P[j].rr)*(P[i].rr-P[j].rr)+(P[i].cc-P[j].cc)*(P[i].cc-P[j].cc)<=(P[i].ra+P[j].ra)*(P[i].ra+P[j].ra))
                //距離小於等於圓心之間的距離
            {
                f[j]=1;
                dfs(j);
                f[j]=0;
            }
        }
    }
    return;
}
int main()
{
    memset(f,0,sizeof(f));
    scanf("%d%d",&r,&c);
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        scanf("%d%d%d",&P[i].rr,&P[i].cc,&P[i].ra);
        if(P[i].rr<=P[i].ra||P[i].cc+P[i].ra>=c)
        {
            cou++;
            rc[cou]=i;//儲存右上角
        }
        if(P[i].cc<=P[i].ra||P[i].ra+P[i].rr>=r)
            fl=1;//儲存左下角
    }
    if(fl==1&&cou>=1)
    {
        for(int i=1; i<=cou; i++)//多個左下角的點逐次判斷
        {
            f[rc[i]]=1;
            dfs(rc[i]);
            f[rc[i]]=0;
        }
        if(fl2==1)
            printf("N");
        else
            printf("S");
    }
    else
        printf("S");
    return 0;
}

相關文章