# 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;
}
```
:::
---