1. 程式人生 > >【題目整理】dfs入門

【題目整理】dfs入門

目錄

模板

dfs對我來說好難qaq可能寫的太少了吧……還是得好好練練

模板

void dfs()//引數用來表示狀態
{
    if(到達終點狀態)
    {
        ...//根據題意來新增
        return;
    }
    if(越界或者是不符合法狀態)
        return;
    for(擴充套件方式)
    {
        if(擴充套件方式所達到狀態合法)
        {
            ....//根據題意來新增
            標記;
            dfs();
            修改(剪枝);
            (還原標記);
            //是否還原標記根據題意
            //如果加上(還原標記)就是 回溯法
        }
        
    }
}

【題意】

給定一個數,輸出一個數的全排列。

【解題思路】

大概是最最基礎的dfs題了,做好標記,記錄好數字,每當c=n時輸出一次就好啦。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
int v[1005],a[1005],n;
void dfs(int c)
{
    if(c==n){
        printf("%d",a[0]);
        for(int i=1;i<n;i++)printf(" %d",a[i]);
        printf("\n");
    }
    else{
        for(int i=1;i<=n;i++){
            if(!v[i]){
                v[i]=1;
                a[c]=i;
                dfs(c+1);
                v[i]=0;
            }
        }
    }
}
int main()
{
    while(~scanf("%d",&n)){
        memset(v,0,sizeof(v));
        memset(a,0,sizeof(a));
        dfs(0);
    }
    return 0;
}

【題意】

給出1-n的整數,看是否能填入環中,使相鄰兩個數的和為素數(1為起點)。

【解題思路】

其實這題和上面一題很像,只是多了一步判斷素數,同樣也是挨個遍歷,因為是個環記得輸出時要判斷一下起點和終點的和是不是素數再輸出。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
int a[25],v[25],k=1,n;
int isprime(int a)
{
    int flag=1;
    if(a==1)return 0;
    else if(a==2)return 1;
    else{
        for(int i=2;i<a;i++){
            if(a%i==0){
                flag=0;
                break;
            }
        }
        if(flag)return 1;
        else return 0;
    }
}
void dfs(int c)
{
    if(c==n && isprime(a[0]+a[c-1])){
        printf("%d",a[0]);
        for(int i=1;i<n;i++)printf(" %d",a[i]);
        printf("\n");
    }
    else{
        for(int i=2;i<=n;i++){
            if(!v[i]){
                if(isprime(i+a[c-1])){
                    v[i]=1;
                    a[c]=i;
                    dfs(c+1);
                    v[i]=0;
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d",&n)){    
        memset(v,0,sizeof(v));
        memset(a,0,sizeof(a));
        printf("Case %d:\n",k++);
        a[0]=1;    
        dfs(1);
        printf("\n");
    }
    return 0;
}

【題意】

計算油田數,連通(周圍8塊都算連通)的油田算一塊,@代表油田。

【解題思路】

只需遍歷每一個點看其是否是油田,如果是並且沒有被標記過則進入搜尋,即搜尋周圍8個位置,搜尋出口是遍歷出界或已被標記或不是油田。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
char a[105][105],v[105][105];
int n,m;
void dfs(int x,int y)
{
    if(x<0 || y<0 || x>=n ||y>=m)return;
    if(a[x][y]=='*' || v[x][y])return;
    v[x][y]=1;
    dfs(x-1,y-1);
    dfs(x-1,y);
    dfs(x-1,y+1);
    dfs(x,y-1);
    dfs(x,y+1);
    dfs(x+1,y-1);
    dfs(x+1,y);
    dfs(x+1,y+1);
}
int main()
{
    while(~scanf("%d%d",&n,&m) && n && m){
        memset(v,0,sizeof(v));
        memset(a,0,sizeof(a));
        getchar();
        for(int i=0;i<n;i++)scanf("%s",a[i]);
        int cnt=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(a[i][j]=='@' && !v[i][j]){
                    dfs(i,j);
                    cnt++;
                }
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

【題意】

在一個吝嗇的國度裡有N個城市,這N個城市間只有N-1條路把這個N個城市連線起來。現在,Tom在第S號城市,他有張該國地圖,他想知道如果自己要去參觀第T號城市,必須經過的前一個城市是幾號城市(假設你不走重複的路)。

【解題思路】

圖的深搜,遍歷每一個城市,記得做好標記,因為N-1條路連N個城市證明圖是連通的,從任一頂點進入搜尋肯定能遍歷所有頂點的,只需要把遍歷的前一頂點在陣列中記錄下來最後輸出陣列即可。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
vector<int>v[100005];
int vis[100005],c[100005];
int dfs(int s)
{
	for(int i=0;i<v[s].size();i++){
		int x=v[s][i];
		if(!vis[x]){
			vis[x]=1;
			//printf("v[%d][%d]=%d\n",s,i,x);
			c[x]=s;
			dfs(x);
		}
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--){
		memset(vis,0,sizeof(vis));
		memset(c,0,sizeof(c));
		for(int i=0;i<100005;i++)v[i].clear();
		int n,s,a,b;
		scanf("%d%d",&n,&s);
		int k=n-1;
		while(k--){
			scanf("%d%d",&a,&b);
			v[a].push_back(b);
			v[b].push_back(a);
		}
		dfs(s);
		c[s]=-1;
		printf("%d",c[1]);
		for(int i=2;i<=n;i++)printf(" %d",c[i]);
		printf("\n");
	}
	return 0;
}

【題意】

有N個城堡,每個城堡都有寶物,每局遊戲中允許他們攻破M個城堡並且獲得獎勵,但是由於地圖的限制,有些城堡不能直接攻破,要攻破這些城堡必須先攻破其他特定的城堡,計算獲得的最多寶物數量。

【解題思路】

還是依次遍歷,每當達到特定城堡數時判斷一下是否可行,若可行則更新ans。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
int f[15],a[15],v[15];
int n,m,ans;
int find()//計算當滿足城堡數量時的寶物數量
{
    int sum=0,cnt=0;
    for(int i=1;i<=n;i++){
        if(v[i]){
            if(!f[i] || v[f[i]]){
                sum+=a[i];
                cnt++;
            }
        }
    }
    if(cnt==m)return sum;
    else return 0;//若這些城堡中有城堡 需要攻擊的前城堡沒被攻擊過 則不能計算入內 所以返回0
}
void dfs(int x,int c)
{
    if(c==m){
        ans=max(ans,find());
        return;
    }
    if(x==n+1)return;
    v[x]=1;
    dfs(x+1,c+1);//攻擊當前城堡
    v[x]=0;
    dfs(x+1,c);//不攻擊當前城堡
}
int main()
{
    while(~scanf("%d%d",&n,&m) && n || m){
        for(int i=1;i<=n;i++)scanf("%d%d",&f[i],&a[i]);
        ans=0;
        memset(v,0,sizeof(v));
        dfs(0,0);
        printf("%d\n",ans);
    }
    return 0;
}

【題意】

掃雷。輸出滑鼠最少需要點幾次可以找到所有的雷。

【解題思路】

即當滑鼠點到0時,0的周圍所有數字都會出現,所以dfs找到每個0以及其周圍的數字作為1個聯通塊,並將它們做好標記,每多1個連通塊答案個數就+1,最後將沒有標記過且不是雷的個數再進行累加即可。

【程式碼】

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=15;
int n,d[8][2]={{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}};;
char s[15][15];
void dfs(int x,int y)
{
    s[x][y]='$';
    for(int i=0;i<8;i++)
    {
        int a=x+d[i][0];
        int b=y+d[i][1];
        if(a<0 || a>=n||b<0 || b>=n)continue;
        if(s[a][b] == '0') dfs(a,b);
		if(s[a][b]!='@' && s[a][b]!='$') s[a][b]='$';
    }
}
int main()
{
    int T,k=1;
    scanf("%d",&T);
    while(T--)
    {
        memset(s,0,sizeof(s));
        int ans=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%s",s[i]);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(s[i][j]=='0')
                {
                    dfs(i,j);
                    ans++;
                }
            }
            //printf("%d\n",ans);
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(s[i][j]!='@' && s[i][j]!='$')ans++;
        printf("Case %d: %d\n",k++,ans);
    }
    return 0;
}

【題意】

查詢有向圖是否存在環。

【解題思路】

5555當時居然沒有寫出來,我的dfs真是太弱了。只要找是否某兩個點之間存在邊,並且該點已經被遍歷過就可以了。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
int edge[maxn][maxn],vis[maxn],flag=1,n;
void dfs(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(vis[i] && edge[x][i])
        {
            flag=0;
            return;
        }
        if(edge[x][i])
        {
            vis[i]=1;
            dfs(i);
            vis[i]=0;
        }
    }
}
int main()
{
    while(~scanf("%d",&n) && n!=-1)
    {
        memset(edge,0,sizeof(edge));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x!=y)
                edge[x][y]=1;
        }
        int t;
        scanf("%d",&t);
        vis[t]=1;
        flag=1;
        dfs(t);
        if(flag)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

相關推薦

題目整理dfs入門

目錄 模板 dfs對我來說好難qaq可能寫的太少了吧……還是得好好練練 模板 void dfs()//引數用來表示狀態 { if(到達終點狀態) { ...//根據題意來新增 retu

題目整理數位dp(入門

先丟一個模板 typedef long long ll; int a[20]; ll dp[20][state];//不同題目狀態不同 ll dfs(int pos,/*state變數*/,bool lead/*前導零*/,bool limit/*數位上界變數*/)//不是每個題都要判斷前導零

題目整理反素數

目錄 Codeforces27E Number With The Given Amount Of Divisors(模板題) zoj 2562 More Divisors(模板題) Codeforces27E Number With The Given Amount Of Divis

題目整理基礎dp

目錄   HDU2859 Phalanx(最大對稱矩陣) HDU1176 免費餡餅 HDU1024 Max Sum Plus Plus(滾動陣列) HDU2859 Phalanx(最大對稱矩陣) 【題意】 給一個矩陣,求這個矩陣的最大對稱矩陣長度。 【解

總結整理javascript基礎入門學習(慕課網學習)

節點 confirm pro remove prompt 例如 ref 存儲 基礎入門 https://www.imooc.com/learn/36 註意: javascript作為一種腳本語言可以放在html頁面中任何位置,但是瀏覽器解釋html時是按先後順序的,所以前面

資料結構高分筆記題目整理

【題意】     如上所示,由正整數1,2,3……組成了一顆特殊二叉樹。我們已知這個二叉樹的最後一個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。     比如,n = 12,m = 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結

自己的整理Vue入門使用

為什麼要用vue 寫這篇部落格的時間,2018年4月20日。我們為什麼要用vue 前端框架層出不窮的今天,選擇一個較為主流同時能讓自己事半功倍的框架是必不可少的,同時vue作為三大主流框架之一發展迅速,如果還沒有選擇好用哪個框架,那不如稍微考慮一下,只要選定

Netty整理01-快速入門Netty簡單使用Demo(已驗證)

多處摘抄或手打,為了十積分厚著臉皮標為原創,慚愧慚愧~本篇文章用於快速入門搭建一個簡單的netty 應用,如想稍微深入系統的瞭解,請參照本人下一篇部落格,連結: 參考地址: 官方文件:http://netty.io/wiki/user-guide-for-4.x.h

SpringMVC架構SpringMVC入門實例,解析工作原理(二)

rip 業務邏輯層 popu 輸入 implement override article hide -i 上篇博文,我們簡單的介紹了什麽是SpringMVC。這篇博文。我們搭建一個簡單SpringMVC的環境,使用非註解形式實現一個HelloWorld實

問題整理php調用python腳本無顯示問題

php python 環境:windows Server2008+Apache+php+MySQL 問題:shell可以執行成功,但是php調用python就不行了 開發一個項目時需要用php調用python命令,如下: $cmd = ‘python

總結整理overflow: auto/hidden;清除自己

12px borde 清除浮動 nav pre flow 需要 效果 size .top-nav{ font-size: 12px; font-weight: bold; li

總結整理http-https

log 整理 消息 cer 基本原理 ati 公鑰加密 簽名 如何 上面這種加密消息的方式就是對稱加密,你知道如何加密,也知道如何解碼。然後李雷跟韓梅梅用的字母表偏移的加密方法叫 Caesar cipher, 凱撒加密。現實世界中用的加密算法會更復雜,但是基本原理相同。 上

總結整理JQuery基礎學習---事件篇

交互 .... over 指針 events 返回值 避免 func 坐標 jQuery鼠標事件之click與dbclick事件 用交互操作中,最簡單直接的操作就是點擊操作。jQuery提供了兩個方法一個是click方法用於監聽用戶單擊操作,另一個方法是dbclick方

總結整理關於跨域

ade OS erro sea pro div 總結 pre utf 1. 代理 北京的服務器:www.beijing.com/service.php 上海的服務器:www.beijing.com/proxy-shanghaiservice 比如在北京的web服務器後臺(w

總結整理json數據請求簡化版理解(祺哥的成果)

如果 body 是你 函數 har 合同 esp 避免 轉換 在同源js目錄下新建.txt文件 { "news":[ {"title":"審計管理","time":"2018-03-10 21:00"}, {"title":"菜單管理","time":

總結整理高德LBS開放平臺學習

eat min 引入 開放 工具箱 view city 體驗 () 高德LBS開放平臺地址 http://lbs.amap.com/api/javascript-api/guide/create-map/mapstye 概述->示例中心Demo體驗->開發

總結整理WebGIS基礎

組件 透明 電子商務 系統 瀏覽器 方法 移動gis 產品 數量 1.萬維網:www是world wide web的簡稱是在超文本基礎上形成的信息網 2.互聯網:即廣域局域網及單機按照一定的通訊協議組成的國際計算機網絡 3.WebGIS:網絡地理信息系統,指基於I

總結整理地圖投影(轉)

相對 十分 body 角度 投影 解析 經緯度坐標 福特 曲面 1.地球橢球體 地球是一個表面很復雜的球體,人們以假想的平均靜止的海水面形成的“大地體”為參照,推求出近似的橢球體,理論和實踐證明,該橢球體近似一個以地球短軸為軸的橢園而旋轉

總結整理arcgis js api的Map類

div eal sna ice click esri 顯示 navi 完成 ArcGis for javascrept_ESRI_Map類:   1. 構造方法:esri.Map();     參數: extent 如果設置了該選項,一旦這個選項的投

總結整理微信產品-張小龍-PM學習總結

的人 重要 二維碼 皮膚 品牌 問題 出發 是否 優化 偉大的產品可以滿足人類的情感需求。找到需求背後的心理訴求產品的終極目標是滿足任性需求,不在產品中摻雜自己的道德感。“我有個好主意”,往往都是脫離用戶需求的。 1,不直接滿足用戶需求2,用戶需求是零散的,解決方案是歸納抽