搜索练习 (主要练剪枝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;
}
时间: 2024-12-14 18:44:45

搜索练习 (主要练剪枝23333)的相关文章

POJ 6048 泰国佛塔 【dfs搜索】【疯狂剪枝!】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 int volumn[25],minArea[25];//volumn[i]为第i层到第1层蛋糕所用最小体积 6 int ans,n,m; //minArea[i]为第i层到第1层蛋糕所用[最小侧面积] 7 int area;//当前dfs状态所需要用的表面积 8 9 int maxV(int level,int r,int h){//用level层蛋

剪枝算法--优化搜索(转载)

转载于:http://princetonboy.ycool.com/post.2805302.html [摘要]本文讨论了搜索算法中“剪枝”这一常见的优化技巧. 首先由回溯法解决迷宫问题展开论述,介绍了什么是剪枝; 而后分析剪枝的三个原则正确.准确.高效,并分别就剪枝的两种思路:可行性剪枝及最优性剪枝,结合例题作进一步的阐述; 最后对剪枝优化方法进行了一些总结. [关键字]搜索.优化.剪枝.时间复杂度 引论 在竞赛中,我们有时会碰到一些题目,它们既不能通过建立数学模型解决,又没有现成算法可以套用

浅谈搜索剪枝

搜索是OI之路上,人人必会的强大算法.自古便有名言:"暴力进省队"(实际上,很多考试你打好所有暴力就可以拿到不错的分数). 在考场上,搜索常常是与正解的对拍板子(当然有时搜索就是正解),且一般搜索都会有20~30分. 而想要写好搜索,剪枝必不可少(有时出题人不会给纯暴力分). what is 剪枝? 常用的搜索有Dfs和Bfs. Bfs的剪枝通常就是判重,因为Bfs寻找的是步数最少,重复的话必定不会在之前的情况前产生最优解. 深搜,它的进程近似一颗树(通常叫Dfs树). 而剪枝就是一种

剪枝的定义&amp;&amp;hdu1010

半年前在POJ上遇到过一次剪枝的题目,那时觉得剪枝好神秘...今天在网上查了半天资料,终于还是摸索到了一点知识,但是相关资料并不多,在我看来,剪枝是技巧,而不是方法,也就是说,可能一点实用的小技巧,让程序可以少判断一点,这就是剪枝,剪枝无处不在, 搜索的进程可以看作是从树根出发,遍历一棵倒置的树—-搜索树的过程.而所谓的剪枝,顾名思义,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是减去了搜索树中的某些“枝条”,故称剪枝.(杭电课件上是这么说的:即剪去解答树上已被证明不可能存在可行解或

1025 数的划分(搜索和递推方法)

难度:普及/提高- 题目类型:递推 提交次数:3 涉及知识:动规 题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. 输入输出格式 输入格式: n,k (6<n<=200,2<=k<=6) 输出格式: 一个整数,即不同的分法. 搜索: 代码: 1 #include<iostream> 2 using namespace std

【转】POJ-2362-Square:简单 DFS+剪枝

思路: 首先将输入的各边长累加求和 即四边形周长sum, 后除4 即边长side,这样 通过DFS 搜索这些sticks能否组合成4根长度均为side 进而确定yes no. 在此 就涉及到搜索顺序了-最优性剪枝: 不难理解 先搜索的小棒子 越长,组合构成side的方式就越少,搜索到结果的时间就越短. SO从最长的棒子开始进行DFS. // num表示已确认组合构成 的side的数目 即所求正方形的边数 // len表示所求正方形边长度 s表示搜索起点 #include<iostream> #

HDU ACM 1010 Tempter of the Bone -&gt;简单搜索

分析:搜索题,注意剪枝. #include<iostream> using namespace std; int dfs(int si,int sj,int ei,int ej,int mt); char map[8][8]; int m,n,fa; int main() { int t,i,j,wall,sti,stj,eni,enj; while(cin>>n>>m>>t &&(n||m||t)) { wall=0; fa=0; for(

DFS + 剪枝策略

一:简介 (1)相信做过ACM的人,都很熟悉图和树的深度优先搜索:算法里面有蛮力法 -- 就是暴力搜索(不加任何剪枝的搜索): (2)蛮力搜搜需要优化时,就是需要不停的剪枝,提前减少不必要的搜索路径,提前发现判断的过滤条件: (3)剪枝的核心问题就是设计剪枝判断方法,哪些搜索路径应当舍弃,哪些搜索路径不能舍弃(保留): (4)高效的剪枝过滤条件需要从局部和全局来考虑问题,发现内在的规律. (5)详细的剪枝算法,请见剪枝算法(算法优化) 二:示例验证 (1)题目来源于 poj 1011 Stick

一道搜索好题

给定一个数S,找任意个正整数a1,a2,…,an,使得它们的和恰好等于S,且它们的倒数之和与1的差不超过10^-6. 输出任意一种方案或者输出无解. S<=10^7 自由搜索 自己加限制:搜索递增 强效剪枝: if(sum+1.0/S>eps+1) return;八位数秒处 #include<cmath> #include<cstdio> using namespace std; const double eps=1e-6; int ans[1001]; bool ok