HDU 1016 DFS基礎題
阿新 • • 發佈:2019-01-25
第一次寫部落格(其實是第二篇),請大佬們不要打我。以下內容純手寫,保證原創,如有部分雷同純屬巧合。
其實我很猶豫很害怕,我一個初學者寫程式碼部落格,怕極了被網路大佬們“追殺”,猶豫多時,我決定以一個初學者的視角寫下這篇東西,如果有什麼網路規則啊,錯誤啊,不好的地方請各位大佬大方指出,我一定改!
深度優先搜尋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的時間複雜度很容易超時,一般需要很強的剪枝語句(我還不會,我太菜了)!
感謝圍觀本人的CSDN處女作!我會懷念的。#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; }