先上题目:
#  [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins#  题目描述农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。
给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。
维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。
#  输入格式第一行一个整数 v v v v v v 
第三行一个整数 g g g g g g n n n n n n 
#  输出格式输出文件只有一行,包括牛必需的最小的饲料种数 p p p p p p 
如果有多个解,输出饲料序号最小的(即字典序最小)。
#  样例 #1#  样例输入 #14 100 200 300 400 3 50  50  50  50 200 300 200 300 900 150 389 399 
#  样例输出 #1#  提示【数据范围】100 % 100\% 1 0 0 % 1 ≤ v ≤ 25 1\le v \le 25 1 ≤ v ≤ 2 5 1 ≤ g ≤ 15 1\le g \le 15 1 ≤ g ≤ 1 5 [ 1 , 1000 ] [1,1000] [ 1 , 1 0 0 0 ] 
USACO 2.1
翻译来自 NOCOW
#  题解太长时间没有刷题,一些简单的深搜也不太会写了。这题不用剪枝直接暴力即可。
#include  <bits/stdc++.h>   using  namespace  std;int  ans[1000 ];int  a[1000 ];int  b[1000 ][1000 ];int  c[1000 ];int  n,m,minn=100000000 ;bool  pd (int  x) 	for (int  i=1 ; i<=n; i++) 	{ 		int  sum=0 ; 		for (int  j=1 ; j<=x; j++) 		sum+=b[c[j]][i]; 		if (sum<a[i]) return  false ; 	} 	return  true ; } void  search (int  t,int  s) 	if (t>m) 	{ 		if (pd (s)) 		{ 			if (s<minn) 			{ 				minn=s; 				for (int  i=1 ; i<=minn; i++) 				{ 					ans[i]=c[i]; 				} 			} 		} 		return ;  	} 	c[s+1 ]=t; 	search (t+1 ,s+1 ); 	c[s+1 ]=0 ; 	search (t+1 ,s); } int  main () 	cin>>n; 	for (int  i=1 ; i<=n; i++) 	cin>>a[i]; 	cin>>m; 	for (int  i=1 ; i<=m; i++) 	{ 		for (int  j=1 ; j<=n; j++) 		cin>>b[i][j]; 	} 	search (1 ,0 ); 	cout<<minn<<' ' ; 	for (int  i=1 ; i<=minn; i++) 	cout<<ans[i]<<' ' ; 	return  0 ; } 
写这个主要是因为第一眼还是 dx,dy 类型的深搜,刚开始手足无措没有想到如何处理这种 0,1 状态的深搜使其能搜索所有的状态。
下面再贴一道纯模板题
#  深さ優先探索#  题面翻译高桥先生住的小区是长方形的,被划分成一个个格子。高桥先生想从家里去鱼店,高桥先生每次可以走到他前后左右四个格子中的其中一个,但不能斜着走,也不能走出小区。
现在给出地图:
```g```:代表鱼店 ```.```:代表道路 ```#```:代表墙壁 高桥先生不能穿过墙壁。 输入:第一行输入n(1<=n<=500),m(1<=m<=500)代表小区的长和宽,接下来n行每行m个字符,描述小区中的每个格子。 输出:如果高桥先生能到达鱼店,输出"Yes",否则输出"No"。 ## 题目描述 [problemUrl]: https://atcoder.jp/contests/atc001/tasks/dfs_a この問題は、講座用問題です。ページ下部に解説が掲載されています。 高橋君の住む街は長方形の形をしており、格子状の区画に区切られています。 長方形の各辺は東西及び南北に並行です。 各区画は道または塀のどちらかであり、高橋君は道を東西南北に移動できますが斜めには移動できません。 また、塀の区画は通ることができません。 高橋君が、塀を壊したりすることなく道を通って魚屋にたどり着けるかどうか判定してください。 ## 输入格式 入力は以下の形式で標準入力から与えられる。 > $ H $ $ W $ $ c_{0,0} $ $ c_{0,1} $ $ c_{0,W-1} $ $ c_{1,0} $ $ c_{1,1} $ $ c_{1,W-1} $ : $ c_{H-1,0} $ $ c_{H-1,1} $ $ c_{H-1,W-1} $ - $ 1 $ 行目には、街の南北の長さとして整数 $ H(1≦H≦500) $ と東西の長さとして整数 $ W(1≦W≦500) $ が空白で区切られて与えられる。 - $ 2 $ 行目からの $ H $ 行には、格子状の街の各区画における状態 $ c_{i,j}(0≦i≦H-1,\ 0≦j≦W-1) $ が与えられる。    - $ i $ 行目 $ j $ 文字目の文字 $ c_{i,j} $ はそれぞれ `s`, `g`, `.`, `#` のいずれかで与えられ、座標 $ (j,i) $ が下記のような状態であることを表す。        - `s` : その区画が家であることを表す。       - `g` : その区画が魚屋であることを表す。       - `.` : その区画が道であることを表す。       - `#` : その区画が塀であることを表す。   - 高橋君は家・魚屋・道は通ることができるが、塀は通ることができない。   - 与えられた街の外を通ることはできない。   - `s` と `g` はそれぞれ 1 つずつ与えられる。 ## 输出格式 塀を $ 1 $ 回も壊さずに、家から魚屋まで辿り着くことができる場合は `Yes`、辿りつけない場合は `No` を標準出力に $ 1 $ 行で出力せよ。 ## 题解 这道题就纯是最常见也是最简单的DFS了,多了一个字符串的转换,这里也可以复习一下getchar()函数和cin和scanf函数, >**cin从第一个非空格、非回车、非tab键的位置开始读取,当与所要读取类型一致时则开始读取,遇上空格、tab键不再读取、回车结束。** >输入缓冲区有数据:从输入缓冲区读取,从非空字符开始,遇到空格结束(回车、空格、tab)。尾回车会被留在输入缓冲区,并且不做处理。   输入缓冲区没有数据:获取键盘输入,当按下回车的时候,输入的数据连同刚按下的回车符被送入输入缓冲区。然后从输入缓冲区区读取数据,规则和上面标黄部分一样。 >1、scanf从非空格字符开始读取,空格字符结束(空格、TAB、回车)    2、当缓冲区没有数据的时候,需要先从键盘输入,然后放入缓冲区再读取。    3、当缓冲区有数据的时候不会从键盘获取数据。我们可以从上面输入看到第二个sacnf并没有从键盘获取数据    4、sacnf会把末尾回车留在缓冲区,给以后的输入埋雷 接着贴上代码 ```cpp #include<bits/stdc++.h> using namespace std; int map1[502][502]; int record[502][502]; #define xx x+dx[i] #define yy y+dy[i] int sx,sy,fx,fy; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int n,m; int flag=0; void dfs(int x,int y){ 	record[x][y]=1; 	if(x==fx&&y==fy){ 		flag=1; 		return; 	} 	if(!flag) 		for(int i=0;i<4;i++){ 			if(xx<=n&&x>0&&y<=m&&y>0&&map1[xx][yy]==0&&record[xx][yy]==0){ 				dfs(xx,yy); 			} 		} 	return; } int main(){ 	cin>>n>>m; 	getchar(); 	for(int i=1;i<=n;i++){ 		for(int j=1;j<=m;j++){ 			char tmp; 			tmp = getchar(); 			if(tmp=='s'){ 				sx = i,sy = j; 				map1[i][j]=0; 			} 			else if(tmp == '#'){ 				map1[i][j]=1; 			} 			else if(tmp == 'g'){ 				fx=i,fy=j; 			} 			else{ 				map1[i][j] = 0; 			} 		} 		getchar(); 	} 	dfs(sx,sy); 	if(flag){ 		cout<<"Yes"<<endl; 	} 	else{ 		cout<<"No"<<endl; 	} 	return 0; } 
再上一题 dfs,其实这一题和放的第一题是同一种类型,或者说是第一和第二的结合,在二维数组中每个元组有选和不选两种状态,这时候应该的做法。
#  取数游戏#  题目描述一个 N × M N\times M N × M 8 8 8 
#  输入格式第一行有一个正整数 T T T T T T 
对于每一组数据,第一行有两个正整数 N N N M M M N N N M M M 
接下来 N N N M M M 
#  题解这里不给出样例输入输出了
#include <iostream>  #include <string.h>  using  namespace  std;int  T;int  N,M;int  map[9 ][9 ];int  maxsum = 0 ;int  enable[8 ][8 ];int  dx[8 ]={0 ,0 ,1 ,1 ,1 ,-1 ,-1 ,-1 };int  dy[8 ]={1 ,-1 ,0 ,1 ,-1 ,1 ,0 ,-1 };int  currentsum = 0 ;#define  xx x+dx[i] #define  yy y+dy[i] void  search (int  x,int  y) 	if (y == M+1 ){ 		search (x+1 ,1 ); 		return ; 	} 	if (x == N+1 ){ 		maxsum = max (maxsum,currentsum); 		return ; 	} 	 	search (x,y+1 ); 	if (enable[x][y]==0 ){ 		currentsum += map[x][y]; 		for (int  i=0 ;i<8 ;i++){ 			enable[xx][yy]++; 		} 		 		search (x,y+1 ); 		 		for (int  i=0 ;i<8 ;i++){ 			enable[xx][yy]--; 		} 		currentsum-=map[x][y];		  	} } int  main () 	cin>>T; 	for (int  i=1 ;i<=T;i++){ 		cin>>N>>M; 		maxsum = 0 ; 		for (int  j=1 ;j<=N;j++){ 			for (int  k=1 ;k<=M;k++){ 				cin>>map[j][k]; 			} 		} 		currentsum=0 ; 		search (1 ,1 ); 		cout<<maxsum<<endl; 	} 	 	 	return  0 ;  }  
这里我第一次写代码时,并没有考虑到所有的情况,向上面这样写才能考虑到所有的情况,因为你需要考虑到每个元组选或不选,要在 search 中体现出来。而我第一次写代码时默认都选择,进行了 n*m 的循环寻找,自然会少一些情况。这算是本题的一点收获。
#  题目描述给出一个 N N N M M M 1 ∼ N 1\sim N 1 ∼ N 1 1 1 
#  输入格式第一行包含 2 2 2 N , M N,M N , M 
接下来 M M M 2 2 2 x , y x,y x , y x x x y y y 
#  输出格式共 N N N i i i 1 1 1 i i i i i i 0 0 0 
#  样例 #1#  样例输入 #1#  样例输出 #1#  提示1 1 1 5 5 5 4 4 4 2 2 2 1 → 2 → 4 → 5 1\to 2\to 4\to 5 1 → 2 → 4 → 5 2 2 2 1 → 3 → 4 → 5 1\to 3\to 4\to 5 1 → 3 → 4 → 5 4 → 5 4\to 5 4 → 5 2 2 2 
对于 20 % 20\% 2 0 % 1 ≤ N ≤ 100 1\le N \le 100 1 ≤ N ≤ 1 0 0 60 % 60\% 6 0 % 1 ≤ N ≤ 1 0 3 1\le N \le 10^3 1 ≤ N ≤ 1 0 3 100 % 100\% 1 0 0 % 1 ≤ N ≤ 1 0 6 1\le N\le10^6 1 ≤ N ≤ 1 0 6 1 ≤ M ≤ 2 × 1 0 6 1\le M\le 2\times 10^6 1 ≤ M ≤ 2 × 1 0 6 
#  题解