---
# System prepended metadata

title: 'Week 10: DFS'
tags: [S3 公開資源]

---

# Week 10: DFS

###### tags: `S3 公開資源`

:::info
時間：04/23 9:00 ~ 17:00
地點：成大資工系新館 **65304** 教室
主題：DFS
直播連結：https://youtube.com/live/a116-co0tIo?feature=share
:::

# 必作題題解

[TOC]

## 三章_第一節

### [UVa 441 - Lotto](http://domen111.github.io/UVa-Easy-Viewer/?441)

撰寫者：fishhh

DFS 裸題，要特別注意的是輸出的地方要弄好
:::info
行末不能有空格
測資與測資間要空一行
最後一筆測資輸出完後 不輸出換行
:::
:::spoiler 參考程式碼
```cpp=
#include<iostream>
using namespace std;
int n,m,lott[100];
void dfs(int dep,bool ch[],int max){
	if(dep==6){
		int cnt = 0;
		for(int i=1;i<=m;i++){
			if(ch[i]){
				cout<<lott[i];
				cnt++;
				if(cnt!=6){
					cout<<" ";
				}
			}
		}
		cout<<"\n";
		return ;
	}
	for(int i=max+1;i<=m;i++){
		ch[i]=1;
		dfs(dep+1,ch,i);
		ch[i]=0;
	}
}
int main(){
	bool oup=1;
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	bool ed[100]={};
	while(cin>>m){
		if(m==0){
			return 0;
		}
		for(int i=1;i<=m;i++){
			cin>>lott[i];
		}
		if(!oup){
			cout<<"\n";
		}
		oup=0;
		dfs(0,ed,0);	
	}
}
```
:::

---

### [UVa 195 - Anagram](http://domen111.github.io/UVa-Easy-Viewer/?195)

撰寫者：fishhh

我覺得我自己的寫法不是很漂亮 但可以提供給你們看一下

作法：紀錄每個字元的數量，並且把它做類似hash的操作，讓他以題目的要求排列
再 DFS ， DFS的同時主要以最多開始拿，然後要避免跟上次拿一樣的(因為這樣就會造成重複排列)

要注意的是我裡面那個 preall 變數，代表的是如果要拿的前面還沒被拿完 那就從 1 開始拿 如果前面都拿完 那就從最多開始拿

我一開始沒寫 preall 結果會在這個 case 被卡掉
:::info
zzzzZ
:::

應該是要輸出
:::info
Zzzzz
zZzzz
zzZzz
...
:::

結果會變成
:::info
Zzzzz
zzzzZ
zzzZz
zzZzz
...
:::

:::spoiler
```cpp=
#include "iostream"
#include "vector"
using namespace std;
int cnt[100]={};
string s;
vector<pair<int,int>> now;
void dfs(int depth,int last_take){
	if(depth==s.size()){
		string ans = "";
		char add;
		for(auto i:now){
			if(i.second%2){
				add = ((i.second-1)/2+'A');
			}
			else{
				add =  ((i.second-2)/2+'a');
			}
			for(int k=0;k<i.first;k++){
				ans+=add;
			}
		}
		cout<<ans<<"\n";
		return ;
	}
	bool preall = 1;
	for(int i=1;i<=60;i++){
		if(cnt[i-1])preall = 0;
		if(i==last_take)continue;
		if(!preall){
			for(int j=1;j<=cnt[i];j++){
				now.push_back({j,i});
				cnt[i]-=j;
				dfs(depth+j,i);
				now.pop_back();
				cnt[i]+=j;
			}
		}
		else{
			for(int j=cnt[i];j>0;j--){
				now.push_back({j,i});
				cnt[i]-=j;
				dfs(depth+j,i);
				now.pop_back();
				cnt[i]+=j;
			}
		}
	}
	return ;
}

int main(){
	int t;
	cin>>t;
	while(t--){
		cin>>s;
		for(int i=0;i<100;i++)cnt[i] = 0;
		for(char c:s){
			if(c>='A'&&c<='Z'){
				cnt[(c-'A'+1)*2-1]++;
			}
			else{
				cnt[(c-'a'+1)*2]++;
			}
			// [a,A,b,B,c,C.....]
		}
		dfs(0,8787);
	}
}
```
:::


---

### [ZJ e446 - 排列生成](https://zerojudge.tw/ShowProblem?problemid=e446)

撰寫者：Eason & 小麥:zap:

遞迴枚舉就好
記得最後把存在陣列的元素統一放到字串在輸出
不然會拿不到最後的 20%

:::spoiler code
```cpp=
#include<bits/stdc++.h>
#define ll long long
#define weakson ios::sync_with_stdio(0), cin.tie(0);
using namespace std;

int n;
int arr[15];
bool is_in[15];

void solve(int cnt){
    if (cnt == n){
        string s;
        for (int i = 0; i < n; i++){
            // 這邊直接輸出 arr[i] 會 TLE
            if (arr[i] != 10) s += arr[i] + '0';
            else s += "10";
            s += ' ';
        }
        cout << s << '\n';
        return;
    }
    for (int i = 1; i <= n; i++){
        if (!is_in[i]){
            arr[cnt] = i;
            is_in[i] = true;
            solve (cnt + 1);
            is_in[i] = false;
        }
    }
    return;
}

int main(){
    weakson;
    cin >> n;
    for (int i = 1; i <= n; i++){
        arr[0] = i;
        is_in[i] = true;
        solve (1);
        is_in[i] = false;
    }
    return 0;
}
```
:::

<br>

:::spoiler 另解
```cpp=
#include <bits/stdc++.h>

using namespace std;

int n;
vector<int> numbers;

void solve() 
{
    cin >> n;

    for (int i = 1; i <= n; i++)
    {
        numbers.emplace_back(i);
    }

    string result = "";
    do
    {
        for (auto i : numbers) 
        {
            result += to_string(i) + ' ';
        }
        result += '\n';
    } while (next_permutation(numbers.begin(), numbers.end()));

    cout << result;
}

signed main() 
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    solve();

    return 0;
}
```
:::

---

### [TOJ 362 - D.大紙牌](https://toj.tfcis.org/oj/pro/362/)

撰寫者：Eason

直接暴力做就好
記得注意邊界

:::spoiler code
```cpp=
#include<bits/stdc++.h>
#define ll long long
#define weakson ios::sync_with_stdio(0), cin.tie(0);
using namespace std;

vector<int> s(18), h(18), d(18), c(18);
bool ans;

void solve(int sp, int hp, int dp, int cp){

    if (ans or (sp == 13 and hp == 13 and dp == 13 and cp == 13)){
        ans = true;
        return;
    }
    if (sp <= 12){
        if (hp <= 12 && s[sp] == h[hp]) solve (sp + 1, hp + 1, dp, cp);
        if (dp <= 12 && s[sp] == d[dp]) solve (sp + 1, hp, dp + 1, cp);
        if (cp <= 12 && s[sp] == c[cp]) solve (sp + 1, hp, dp, cp + 1);
    }
    if (hp <= 12){
        if (dp <= 12 && h[hp] == d[dp]) solve (sp, hp + 1, dp + 1, cp);
        if (cp <= 12 && h[hp] == c[cp]) solve (sp, hp + 1, dp, cp + 1);
    }
    if (dp <= 12){
        if (cp <= 12 && d[dp] == c[cp]) solve (sp, hp, dp + 1, cp + 1);
    }
    return;
}

int main(){
    weakson;

    for (int i = 0; i < 13; i++) cin >> s[i];
    for (int i = 0; i < 13; i++) cin >> h[i];
    for (int i = 0; i < 13; i++) cin >> d[i];
    for (int i = 0; i < 13; i++) cin >> c[i];

    solve (0, 0, 0, 0);

    if (ans) cout << "YES\n";
    else cout << "NO\n";

    return 0;
}

```
:::

---

### [TOJ 432 - Akechi 明智的選擇](https://toj.tfcis.org/oj/pro/432/)

撰寫者：Eason

用 DFS 解就好了

:::spoiler code
```cpp=
#include<bits/stdc++.h>
#define ll long long
#define weakson ios::sync_with_stdio(0), cin.tie(0);
using namespace std;

int n, m;
int arr[1005][1005];
bool visited[1005][1005];

int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};

bool dfs(int x, int y){
    if (arr[x][y] == 1) return true;
    for (int i = 0; i < 4; i++){
        int rx = x + dx[i];
        int ry = y + dy[i];

        if (rx <= n && rx >= 1){
            if (ry <= m && ry >= 1){
                if (!visited[rx][ry]){
                    visited[rx][ry] = true;
                    if (dfs (rx, ry)){
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

int main(){
    weakson;
    cin >> n >> m;

    int x, y;
    cin >> x >> y;
    arr[x][y] = 1;

    int u, v;
    cin >> u >> v;

    int f;
    cin >> f;
    for (int i = 0; i < f; i++){
        cin >> x >> y;
        visited[x][y] = 1;
    }

    if (dfs(u, v)) cout << "Cool!\n";
    else cout << "Harakiri!\n";

    return 0;
}
```
:::

---

### [33TOJ 487 - 停止爆炸](https://toj.tfcis.org/oj/pro/487/)

撰寫者：小麥

BFS水題


:::spoiler code
```cpp=
#include <bits/stdc++.h>

using namespace std;

struct Point
{
    int x;
    int y;
};

vector<int> dx = {1, -1, 0, 0};
vector<int> dy = {0, 0, 1, -1};
vector<vector<int>> world;
vector<vector<int>> visited;
queue<Point> bfs;
int n, m;
Point creeper;
Point player;

void solve() 
{
    cin >> n >> m;
    world.resize(n, vector<int>(m));
    visited.resize(n, vector<int>(m));
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> world[i][j];
        }
    }
    cin >> creeper.x >> creeper.y;
    cin >> player.x >> player.y;
    creeper.x -= 1;
    creeper.y -= 1;
    player.x -= 1;
    player.y -= 1;
    
    bfs.push(creeper);
    visited[creeper.x][creeper.y] = 1;
    while (bfs.size())
    {
        Point top = bfs.front();
        bfs.pop();

        int distance = abs(top.x - player.x) + abs(top.y - player.y);
        if (distance <= 3)
        {
            cout << "yes" << '\n';
            return;
        }
        for (int i = 0; i < 4; i++)
        {
            int x = top.x + dx[i];
            int y = top.y + dy[i];
            if (!(x >= 0 && x < n))
            {
                continue;
            }
            if (!(y >= 0 && y < m))
            {
                continue;   
            }
            Point next;
            next.x = x;
            next.y = y;
            int diff = world[next.x][next.y] - world[top.x][top.y];
            if (!(diff <= 1 && diff >= -2)) 
            {
                continue;
            }
            if (visited[next.x][next.y] == 1)
            {
                continue;
            }

            bfs.push(next);
            visited[next.x][next.y] = 1;
        }
    }

    cout << "no" << '\n';
}

signed main() 
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    solve();

    return 0;
}
```
:::

---

