例题1:zjut 1398(全排列)http://acm.zjut.edu.cn/ShowProblem.aspx?ShowID=1398
加入了剪枝,即在全排列中不能输出重复排列,还有就是需要排序
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=100;
bool visit[MAX];
string s,s1;
string s2="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
void DFS(int cur)
{ int len=s.length();
if(cur==len)
{ for(int i=0;i<len;i++)
cout<<s1[i];
cout<<endl;
}
else
for(int i=0;i<len;++i)
{ if(!visit[i])
{ if(i&&!visit[i-1]&&s[i]==s[i-1]) continue;
visit[i]=true;
s1[cur]=s[i];
DFS(cur+1);
visit[i]=false;
}
}
}
int main()
{ int n;
cin>>n;
getchar();
while(n--)
{ cin>>s;
for(int i=0;i<s.length();i++)
for(int j=i+1;j<s.length();j++)
if(s2.find(s[i])>s2.find(s[j])) swap(s[i],s[j]); //排序
DFS(0);
}
return 0;
}
这道题做完后可以做POJ 1256了~~
hdu 1241(以前是用BFS做的,现在用DFS做,发现还简单些,呵呵呵~~)题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241
#include<iostream>
using namespace std;
const int MAX=110;
char map[MAX][MAX];
int dx[8]={0,1,1,1,0,-1,-1,-1};//水平方向的坐标变化
int dy[8]={-1,-1,0,1,1,1,0,-1};//垂直方向的坐标变化
int n,m;
int Inside(int x,int y)
{ return x>=0&&x<n&&y>=0&&y<m;
}
void DFS(int x,int y)
{ for(int i=0;i<8;i++)
{ int Newx=dx[i]+x;
int Newy=dy[i]+y;
if(Inside(Newx,Newy)&&map[Newx][Newy]=='@')//要保证在范围内
{ map[Newx][Newy]='*';//要调整过来,搜过了的可以用@外的任意字符代替
DFS(Newx,Newy);
}
}
}
int main()
{ while(cin>>n>>m&&m||n)
{ int step=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>map[i][j];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(map[i][j]=='@')
{ step++;
DFS(i,j);
}
cout<<step<<endl;
}
return 0;
}
例题3:nyist 325 (zb的生日)题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=325
//abs(a-b)=abs((sum-b)-b)=abs(sum-2*b),所以只需搜其中一个人的即可,用甲乙表示~
#include<iostream>
#include<cstdlib>
using namespace std;
int a[25];
int Max,sum;
void DFS(int cur,int m)//cur是用来保存其中一人的西瓜重量~,用甲表示
{ if(m<0) return ;
if(Max>abs(sum-2*cur)) Max=abs(sum-2*cur);
DFS(cur+a[m],m-1); //甲要a[m]这个西瓜,则甲的西瓜重量+a[m],搜索下一个西瓜。
DFS(cur,m-1); //甲不要这个西瓜m则直接搜索下一个西瓜。
}
int main()
{ int n;
while(cin>>n)
{ sum=0;
Max=1000000000;
for(int i=0;i<n;i++)
{ cin>>a[i];
sum+=a[i];
}
DFS(0,n-1);
cout<<Max<<endl;
}
return 0;
}
例题4:hdu 1010题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
知识点:奇偶剪枝
把矩阵看成如下形式:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
从为 0 的格子走一步,必然走向为 1 的格子 。
从为 1 的格子走一步,必然走向为 0 的格子 。
即:
从 0 走向 1 必然是奇数步,从 0 走向 0 必然是偶数步。
所以当遇到从 0 走向 0 但是要求时间是奇数的或者 从 1 走向 0 但是要求时间是偶数的,都可以直接判断不可达!
#include<iostream>
#include<cstring>
using namespace std;
int dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
char map[7][7];
int M,N,T,flag,ex,ey;
int Inside(int x,int y)
{ return x>=0&&x<N&&y>=0&&y<M;
}
void DFS(int x,int y,int cur)
{ if(x==ex&&y==ey&&cur==T) flag=1;
if(cur>T||flag) return ;
if(T-cur<abs(ex-x)+abs(ey-y)) return ;//剩余时间小于理论值
if((T-cur)%2!=(abs(ex-x)+abs(ey-y))%2) return ;//奇偶剪枝!!
for(int i=0;i<4;i++)
{ int Newx=dx[i]+x;
int Newy=dy[i]+y;
if(Inside(Newx,Newy)&&map[Newx][Newy]!='X')
{ map[Newx][Newy]='X';
DFS(Newx,Newy,cur+1);
map[Newx][Newy]='.';//回溯~~~
}
}
}
int main()
{ int sx,sy;
while(cin>>N>>M>>T&&N||M||T)
{ int num=0;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
{ cin>>map[i][j];
if(map[i][j]!='X') num++;
if(map[i][j]=='S') sx=i,sy=j;
if(map[i][j]=='D') ex=i,ey=j;
}
map[sx][sy]='X';
if(num<T) puts("NO");
else
{ flag=0;
DFS(sx,sy,0);
if(flag) puts("YES");
else puts("NO");
}
}
return 0;
}
例题5:hdu 1181题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1181
深度遍历,首字母为b,直到字符串的最后一个字母为m停止,主要是注意输入。。。。得看清楚题目
#include<iostream>
#include<string>
using namespace std;
string s[105],s1;
int num,flag;
bool visit[105];
void DFS(char c)
{ if(c=='m') flag=1;
if(flag) return ;
else
for(int i=0;i<num;i++)
if(!visit[i]&&s[i][0]==c)
{ visit[i]=true;
int len=s[i].length();
DFS(s[i][len-1]);
visit[i]=false;
}
}
int main()
{ num=0;
while(cin>>s1)
{ s[num++]=s1;
if(s1=="0")
{ flag=0;
for(int i=0;i<num;i++)
{ if(s[i][0]=='b')
{ memset(visit,false,sizeof(visit));
DFS('b');
if(flag) cout<<"Yes."<<endl;
}
if(flag) break;
}
if(!flag) cout<<"No."<<endl;
num=0;//开始看错了题目,输入一直感觉不对劲,原来它是以0作为一组字符串结束,可能还会输入下一组,所以num=0;
}
}
return 0;
}
例题6:nyist 82(迷宫寻宝一)题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=82
分析:深搜问题,当然可以用广搜,就是要求稍微复杂点,昨天晚上RE了一页,郁闷,直到刚刚才做出来,比方说一个图,每个门的钥匙个数各不相同,我们要开这个门的话就要求找到这个门的所有钥匙,下面的代码中用Key[]保存开每扇门的所需的钥匙数,当然这个不一定需要开所有的门,只要开了某扇门后能够找到出口即可,具体看代码,写的比较的乱~~~
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=25;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,m,flag,Startx,Starty,Endx,Endy;
int visit[5],num[5],Key[5];
int dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
char map[MAX][MAX];
struct point{
point(){px=-1;py=-1;}
point(int x,int y):px(x),py(y){}
int px,py;
}D[5];
int Inside(int x,int y)
{ return x>=0&&x<n&&y>=0&&y<m;
}
void DFS(int x,int y)
{ if(x==Endx&&y==Endy) flag=1;
if(flag) return ;
for(int i=0;i<4;i++)
{ int Newx=x+dx[i];
int Newy=y+dy[i];
char c=map[Newx][Newy];
if(c!='X'&&Inside(Newx,Newy))
{ if(c>='A'&&c<='E')
{ visit[c-'A']=1;//记录该扇门是否出现过
D[c-'A'].px=Newx,D[c-'A'].py=Newy;//记录该扇门的位置
if(num[c-'A']!=Key[c-'A']) continue ;//若是不满足找到的钥匙的个数等于需要的钥匙数则不进行深搜
}
if(c>='a'&&c<='e')
{ num[c-'a']++;
if(visit[c-'a']&&num[c-'a']==Key[c-'a']) DFS(D[c-'a'].px,D[c-'a'].py);//前提是这扇门已经被访问过
}
map[Newx][Newy]='X';//不需回溯,因为要找钥匙
DFS(Newx,Newy);
}
}
}
int main()
{ int i,j;
while(cin>>n>>m&&n||m)
{ flag=0;
CLR(Key,0);
CLR(num,0);
CLR(visit,0);
for(i=0;i<n;i++)
cin>>map[i];
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{ char c=map[i][j];
if(c=='S') Startx=i,Starty=j;
if(c=='G') Endx=i,Endy=j;
if(c>='a'&&c<='e') Key[c-'a']++;
}
DFS(Startx,Starty);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}