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

Posted 一入OI深似海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搜索练习 (主要练剪枝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)的主要内容,如果未能解决你的问题,请参考以下文章

poj练习题的方法

蓝桥杯每日一练专栏导读

算法练习之两数之和

搜索专题练习

蓝桥杯每日一练专栏导读

每日一练任务:CSS3预加载动画