DFS(3)

来源:互联网 发布:js onmousemove 编辑:程序博客网 时间:2024/06/06 02:39

例题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;}


 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

原创粉丝点击