1. 程式人生 > >HDU 1016 DFS基礎題

HDU 1016 DFS基礎題

             第一次寫部落格(其實是第二篇),請大佬們不要打我。以下內容純手寫,保證原創,如有部分雷同純屬巧合。

       其實我很猶豫很害怕,我一個初學者寫程式碼部落格,怕極了被網路大佬們“追殺”,猶豫多時,我決定以一個初學者的視角寫下這篇東西,如果有什麼網路規則啊,錯誤啊,不好的地方請各位大佬大方指出,我一定改大哭大哭大哭!

       深度優先搜尋dfs就是一條路走到底,不通就回頭繼續下一個嘗試,直到所有可能都被嘗試完就結束。

       核心思想就是遞迴,回溯。

       程式碼框架就是終止條件,標記點,下一步dfs遞迴呼叫,返回。dfs多次出現return語句。

題目傳送門

(個人喜歡藍色怪我咯)

              正文:我是初學者,希望用CSDN見證我的人生,寫的不好,請各位大佬大膽指出,但請言語不要過激,謝謝。我愛ACM。

       這是一道DFS基礎題,沒什麼難點,資料量也低,不容易超時,所以也不需要剪枝(我還沒學剪枝大哭大哭 來自鹹魚的絕望)。

       下面這個程式碼我自我感覺良好啊,哇,寫了很久,測試多次,以為能一次AC吧,呵呵!妄想。是菜就是菜,還敢妄想AC。至於錯在哪呢?不妨先自己查查bug。

        程式碼WA+PE+TE,哈哈,錯的有點尷尬。

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;

int n;                      //全域性變數,因為dfs中會用到
int a[22];                  //一般dfs陣列都定義為全域性變數,初值為0
bool book[22];              //標記陣列,初始值為false,但最好還是在main裡進行清零操作(即memset函式)

bool fun(int t)             //判定素數函式
{
    for(int i=2; i<t; i++)
        if(t%i==0)
            return false;
    return true;
}

void dfs(int step)
{
    if(step==n+1)             //步數為n+1表示所有數都用上了,即終點,返回
    {
        if(fun(1+a[step-1]))  //到達終點後要把最後一個數和1的和進行素數判定
        {
            for(int j=1; j<step; j++)
                cout << a[j] << ' ';
            cout << endl;
        }
        return;
    }
    for(int i=1; i<=n; i++)
    {
        if(book[i])           //標記過的數都跳過
            continue;
        if(fun(i+a[step-1]))  //判別素數
        {
            book[i]=true;     //標記為已用或已走
            a[step]=i;        //當前步的值
            dfs(step+1);      //進行下一步dfs,此處step不是點,是步數
            book[i]=false;    //一條路走不通就取消標記
        }
    }
    return;                   //所有路都不通就返回
}

int main()
{
    cin >> n;
    memset(book,false,sizeof(book));   //標記陣列清零函式,有些oj好像不需要,但寫上總沒壞處吧
    book[1]=true;             //標記一號點為已走
    a[1]=1;                   //題目預設a[1]=1
    dfs(2);                   //從第二步開始dfs,理由同上
    return 0;
}

    上面得程式碼講道理是沒錯得,錯就錯在HDU有嚴格得格式要求(人稱“坑”)。所以說你完全可以不再看我下面得完整程式碼,自己修改上面得格式即可得到AC答案

    改用scanf和printf是因為我害怕超時,dfs的時間複雜度很容易超時,一般需要很強的剪枝語句(我還不會,我太菜了)!

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;

int n;                      //全域性變數,因為dfs中會用到
int a[22];                  //一般dfs陣列都定義為全域性變數,初值為0
bool book[22];              //標記陣列,初始值為false,但最好還是在main裡進行清零操作(即memset函式)

bool fun(int t)             //判定素數函式
{
    for(int i=2; i<t; i++)
        if(t%i==0)
            return false;
    return true;
}

void dfs(int step)
{
    if(step==n+1)             //步數為n+1表示所有數都用上了,即終點,返回
    {
        if(fun(1+a[step-1]))  //到達終點後要把最後一個數和1的和進行素數判定
        {
            printf("%d",a[1]);
            for(int j=2; j<step; j++)
                printf(" %d",a[j]);
            printf("\n");
        }
        return;
    }
    for(int i=1; i<=n; i++)
    {
        if(book[i])           //標記過的數都跳過
            continue;
        if(fun(i+a[step-1]))  //判別素數
        {
            book[i]=true;     //標記為已用或已走
            a[step]=i;        //當前步的值
            dfs(step+1);      //進行下一步dfs,此處step不是點,是步數
            book[i]=false;    //一條路走不通就取消標記
        }
    }
    return;                   //所有路都不通就返回
}

int main()
{
    int sum=1;
    while(scanf("%d",&n)!=EOF)
    {
        printf("Case %d:\n",sum++);
        memset(book,false,sizeof(book));   //標記陣列清零函式,有些oj好像不需要,但寫上總沒壞處吧
        book[1]=true;             //標記一號點為已走
        a[1]=1;                   //題目預設a[1]=1
        dfs(2);                   //從第二步開始dfs,理由同上
        printf("\n");
    }
    return 0;
}
感謝圍觀本人的CSDN處女作!我會懷念的。