DFS

来源:互联网 发布:怎么重置mac 编辑:程序博客网 时间:2024/04/30 18:18

ZOJ3607 油田问题的变形,主要靠怎么找到相邻点对应的相邻边 然后进行比较

1.要注意dx dy 与 edge中四个方向匹配,数组下标与坐标系的方向是不一样的

2.f==0&&edge[x][0]==1&&edge[y][2]==1  f是用来表示判断哪条相邻边的,不能写成edge[x][0]==edge[y][2],会出现都等于0的情况

#include<iostream>#include<cstdio>#include<cstring>#include<string>#define MAXN 55using namespace std;int vis[MAXN][MAXN],dota[MAXN][MAXN];int n,m;int dx[4]={0,-1,0,1};int dy[4]={-1,0,1,0};int edge[12][5]={{1,1,0,0},{0,1,1,0},{1,0,0,1},{0,0,1,1},{0,1,0,1},{1,0,1,0},{1,1,1,0},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,1}};int fun(int x,int y,int f){    if(f==0&&edge[x][0]==1&&edge[y][2]==1)return 1;    if(f==2&&edge[x][2]==1&&edge[y][0]==1)return 1;    if(f==1&&edge[x][1]==1&&edge[y][3]==1)return 1;    if(f==3&&edge[x][3]==1&&edge[y][1]==1)return 1;    return 0;}void dfs(int a,int b){    vis[a][b]=1;    int p1,p2;    p1=dota[a][b];    for(int i=0;i<4;i++)    {        int x=a+dx[i];        int y=b+dy[i];        if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y])        {            p2=dota[x][y];            //printf("//%d %d %d %d %d\n",x,y,p1,p2,i);            if(fun(p1,p2,i))//可连递归            {                // printf("//%d %d %d %d %d\n",x,y,p1,p2,i);                dfs(x,y);            }        }    }}int main(){   // a[0]={}    while(cin>>n>>m)    {        if(n<=0||m<=0)break;        int i,j;        char ch;        for(i=0;i<n;i++)        {            for(j=0;j<m;j++)            {                cin>>ch;                dota[i][j]=ch-'A';            }        }        memset(vis,0,sizeof(vis));        int sum=0;        for(i=0;i<n;i++)        {            for(j=0;j<m;j++){                    if(!vis[i][j]){                            sum++;                         //   printf("*** %d %d\n",i,j);                            dfs(i,j);                    }            }        }        printf("%d\n",sum);    }    return 0;}


ZOJ2734

题意是给不同价值卡片若干张,问几种方法可以凑成数字n

#include<cstdio>#include<cstring>using namespace std;int n,m,way,sum;int num[1010];void dfs(int x){    if(sum==n){        way++;        return;    }    for(int i=x;i<=n;i++)//超过n-sum后无意义,从x开始(精髓)    {        if(num[i])        {            if(sum+i>n)return;            sum+=i;            num[i]--;            dfs(i);            num[i]++;            sum-=i;        }    }}int main(){    int k=0;    while(~scanf("%d%d",&n,&m))    {        int x,y,i;        memset(num,0,sizeof(num));        for(i=0;i<m;i++){             scanf("%d%d",&x,&y);             num[x]=y;        }        sum=0;        way=0;        dfs(0);        if(k)printf("\n");        k=1;        printf("%d\n",way);    }    return 0;}

ZOJ1666

方法与上题同,不赘述

#include<cstdio>#include<cstring>using namespace std;int n,num[18],sum,way;void dfs(int x){    if(sum==n)    {        way++;        return;    }    for(int i=x;i<17;i++)    {        if(sum+num[i]>n)return;        sum+=num[i];        dfs(i);        sum-=num[i];    }}int main(){    for(int i=1;i<=17;i++)num[i-1]=i*i;    while(~scanf("%d",&n)&&n)    {        sum=0;        way=0;        dfs(0);        printf("%d\n",way);    }    return 0;}

ZOJ1457素数环

简单的dfs,但要考虑一点:n位奇数时不会有答案,因为奇数个数必有两个加起来是偶数

#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define N 100int pri[N],n,vis[N],ans[N];void dfs(int s,int cnt){    int i;    ans[cnt]=s;   // if(cnt>n)return;    if(cnt==n)    {        if(!pri[s+1]){            for(i=1;i<=n;i++)            {                if(i==1)printf("%d",ans[i]);                else printf(" %d",ans[i]);            }            printf("\n");        }        return;    }    for(i=2;i<=n;i++)    {        if(!vis[i]&&!pri[s+i])        {            vis[i]=1;            dfs(i,cnt+1);            vis[i]=0;        }    }}int main(){    memset(pri,0,sizeof(pri));    pri[0]=1;    pri[1]=1;    int i,j,k=1;    for(i=2;i<N;i++)    {        for(j=i*i;j<N;j+=i)pri[j]=1;    }   // for(i=0;i<100;i++)if(!pri[i])printf("%d\n",i);    while(cin>>n)    {        memset(vis,0,sizeof(vis));        vis[1]=1;        printf("Case %d:\n",k++);        if(n%2==0)             dfs(1,1);        printf("\n");    }    return 0;}

ZOJ1711

简单的dfs,关键是去重,本来以为重复的一定是上一个输出等于下一个输出,没想到中间还会隔几个

比如 9 9 5 5 4 4 3 3 2 2 1 1这个例子

应该输出:

Sums of 9:
5+4
5+3+1
5+2+2
4+4+1
4+3+2
4+2+2+1
3+3+2+1

代码:

#include<iostream>#include<cstdio>#include<string>#include<cstring>using namespace std;int a[20],vis[20],n,m;int ans[20],f;int pre[1000][20],num;int quchong(int cnt){    int i,j,s;    for(int i=0;i<num;i++)    {        s=0;        for(j=0;j<cnt;j++){            if(pre[i][j]==ans[j])s++;        }        if(s==cnt)return 1;    }    return 0;}void dfs(int sum,int cnt,int k){    int i;    if(sum>n)return; //   printf("   %d %d\n",sum,cnt);    if(sum==n){        f=1;        if(quchong(cnt))return;        for(i=0;i<cnt;i++){            if(i==0)printf("%d",ans[i]);            else printf("+%d",ans[i]);        }        printf("\n");        for(i=0;i<cnt;i++)pre[num][i]=ans[i];        num++;       // for(i=0;i<str.size();i++)printf("%d\n",str[i]);    }    for(i=k;i<m;i++)    {        if(!vis[i])        {            vis[i]=1;            ans[cnt]=a[i];            dfs(sum+a[i],cnt+1,i+1);            vis[i]=0;        }    }}int main(){    while(cin>>n>>m)    {        if(n==0)break;        int i;        for(i=0;i<m;i++)cin>>a[i];        memset(vis,0,sizeof(vis));        f=0;        num=0;        memset(pre,-1,sizeof(pre));        printf("Sums of %d:\n",n);        dfs(0,0,0);        if(f==0)printf("NONE\n");    }    return 0;}/*9 9 5 5 4 4 3 3 2 2 1 1*/

ZOJ3706

题意:

两个正整数的砝码,把其中一个分成正整数的部分,用这三个砝码能称量哪些重量(正整数)。

解法:

枚举分哪个、分成多少,dfs搜。

画个树状图就很好理解,暴力强搜就可以了。

#include<cstdio>#include<iostream>#include<cstring>using namespace std;int num[3];int cnt;int vis[300];void dfs(int n,int val){    if(n>3)return;    if(val>0&&!vis[val])    {        vis[val]=1;        cnt++;    }    dfs(n+1,val+num[n]);    dfs(n+1,val-num[n]);    dfs(n+1,val);}int main(){    int t;    cin>>t;    while(t--)    {        int n,m,ma,i;        cin>>n>>m;        ma=0;        num[3]=0;        for(i=1;i<=n/2;i++)        {            memset(vis,0,sizeof(vis));            num[0]=i;            num[1]=n-i;            num[2]=m;            cnt=0;            dfs(0,0);            if(cnt>ma)ma=cnt;        }        for(i=1;i<=m/2;i++)        {            memset(vis,0,sizeof(vis));            num[0]=i;            num[1]=m-i;            num[2]=n;            cnt=0;            dfs(0,0);            if(cnt>ma)ma=cnt;        }        printf("%d\n",ma);    }    return 0;}





0 0
原创粉丝点击