首页 > 代码库 > 搜索练习 (主要练剪枝23333)

搜索练习 (主要练剪枝23333)

/*hdu 1010 Tempter of the Bone 尼玛博客里的题目描述不对...加个奇偶剪枝可以证明 两个点之间任意距离与欧几里得距离同奇偶奇偶剪枝 可行性剪枝 特判剪枝... */#include<iostream>#include<cstdio>using namespace std;int n,m,T,sx,sy,ex,ey;bool falg;char s[10][10];int xx[4]={0,0,1,-1};int yy[4]={1,-1,0,0};int Abs(int x){    return x>0?x:-x;}void Dfs(int x,int y,int t){    int S=Abs(ex-x)+Abs(ey-y);    if((S%2&&t%2==0)||(S%2==0&&t%2))return;    if(t<0||S>t)return;    if(t==0&&x==ex&&y==ey){        falg=1;return;    }    for(int i=0;i<4;i++){        int nx=x+xx[i];        int ny=y+yy[i];        if(nx>0&&nx<=n&&ny>0&&ny<=m&&s[nx][ny]==.){            s[nx][ny]=X;            Dfs(nx,ny,t-1);if(falg)return;            s[nx][ny]=.;        }    }}int main(){    while(1){        scanf("%d%d%d",&n,&m,&T);        if(n==0&&m==0&&T==0)break;        falg=0;int cnt=0;        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++){                cin>>s[i][j];                if(s[i][j]==S)sx=i,sy=j,s[i][j]=X;                if(s[i][j]==D)ex=i,ey=j,s[i][j]=.;                if(s[i][j]==.)cnt++;            }        if(cnt+1<T){            printf("NO\n");continue;        }        Dfs(sx,sy,T);        if(falg)printf("YES\n");        else printf("NO\n");    }    return 0;}
/* codevs 1288 埃及分数 迭代+剪枝*/#include<iostream>#include<cstdio>#define ll long long#define C 0.0000001#define mem(a,b) for(int i=0;i<now;i++)a[i]=c[i];using namespace std;ll a,b,falg,sum,ans[110],c[110];ll Gcd(ll x,ll y){    return y?Gcd(y,x%y):x;}ll Ceil(double x){    return int(x+0.99999999);}ll max(ll x,ll y){    return x>y?x:y;}void Dfs(ll x,ll y,ll now){    ll gcd=Gcd(x,y);    x/=gcd;y/=gcd;    if(now==sum){        if(x==0){            if(falg){                if(c[now-1]<ans[now-1])mem(ans,c);            }            else mem(ans,c);            falg=1;        }        return;    }    ll l=Ceil(double(y)/double(x));// 计算左边界     ll r=Ceil((double(sum)-double(now))/(double(x)/double(y)));//计算右边界     for(int i=max(l,c[now-1]+1);i<=r;i++){        if(falg&&i>ans[sum-1])return;        //这个一开写的是再选最后一位的时候才剪 其实只有存过答案了 不管哪一位都能剪 因为后面的一定比这个大         c[now]=i;Dfs(x*i-y,y*i,now+1);c[now]=0;    }}int main(){    cin>>a>>b;    for(sum=1;sum<=20;sum++){        Dfs(a,b,0);        if(falg)break;    }    for(int i=0;i<sum;i++)        cout<<ans[i]<<" ";    return 0;}
/* poj 1416 Shredding Company 简单搜索*/#include<cstdio>#include<cstring>#define mem(a,b) for(int i=1;i<=8;i++)a[i]=b[i];#define mes(a) for(int i=1;i<=8;i++)a[i]=0;using namespace std;int len,target,a[10],c[10],mxx,sum,ans[10];char s[10];void Dfs(int now){    if(now==len){        int mx=0,p=1;        while(p<=len){            int x=a[p];            while(c[p]==0&&p<len){                p++;x=x*10+a[p];            }            mx+=x;p++;        }        if(mx<=target&&mx>mxx){            mxx=mx;sum=1;mem(ans,c);        }        else if(mx<=target&&mx==mxx)sum++;        return;    }    c[now]=1;Dfs(now+1);    c[now]=0;Dfs(now+1);}int main(){    for(;;){        scanf("%d%s",&target,s);        mxx=sum=0;mes(c);        if(target==0&&s[0]==0)break;        len=strlen(s);        for(int i=1;i<=len;i++)            a[i]=s[i-1]-0;        Dfs(1);        if(sum==0)printf("error\n");        else if(sum>1)printf("rejected\n");        else {            printf("%d ",mxx);            for(int i=1;i<=len;i++){                printf("%d",a[i]);                if(ans[i])printf(" ");            }            printf("\n");        }    }    return 0;}

 

搜索练习 (主要练剪枝23333)