埃及分数 IDS 搜索 Vijos 1308

12 篇文章 0 订阅
8 篇文章 0 订阅

传送门
搜索套餐第二题 迭代加深
比较经典 由于他在时间和空间上的搜索层数都是未知
所以我们呢可以给他一个预定的层数进行搜索
如果本层不存在最优解
那就跳到下一层再进行搜索

对于每一层的搜索注意剪枝
首先是可行性剪枝 对于本数 如果本数大于所要的 那么T掉本点
如果本数乘三尚且小于所求 T掉本点
注意分数的性质 注意通分
注意字典序最小的要求
吐槽一下 本题数据略弱
下面是AC代码 略慢  可优化

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
long long  s[500],ans[500],sr,ar;
struct score
{
    long long up,down;
    score () {}
    score (long long x,long long y)
    : up(x),down(y) {x=x/__gcd(x,y);y=y/__gcd(x,y);}
    double calc()
    {return 1.0*up/down;}
};
score operator-(score A,score B)
{
    long long tmp1=A.up,tmp2=A.down,tmp3=B.up,tmp4=B.down;
    tmp1*=tmp4,tmp3*=tmp2;tmp1-=tmp3;
    tmp2*=tmp4;
    long long k=__gcd(tmp1,tmp2);
    tmp1/=k,tmp2/=k;
    score C(tmp1,tmp2);
    return C;
}
bool operator<(score A,score B)
{return A.calc() < B.calc();}
score operator*(int x,score B)
{score C(B.up*x,B.down);return C;}
int tot;
bool cmp=false;
void check()
{
    long long tmp1=sr,tmp2=ar;
    if(!ar)
    {for(int i=1;i<=sr;++i)ans[i]=s[i];ar=sr;return;}
    if(s[tmp1]>ans[tmp2])return;
    if(s[tmp1]<ans[tmp1])
        {for(int i=1;i<=sr;++i)
    ans[i]=s[i];return ;}
    tmp1=1;
    while(ans[tmp1]==s[tmp1])tmp1++;
    if(ans[tmp1]>s[tmp1])
    for(int i=tmp1;i<=sr;++i)
    ans[i]=s[i];
}
void put()
{
    for(int i=1;i<ar;++i)
        printf("%lld ",ans[i]);
    printf("%lld",ans[ar]);
}
void DFS(score A,int depth,int x,int will)
{
    if(depth >= will)
    {if(A.up==1){s[++sr]=x;s[++sr]=A.down;if(s[sr]==s[sr-1]){sr-=2;return ;}check();sr-=2;cmp=true;}return;}
    if(1.0*(will-depth+1)/x<A.calc())return;
    double tmp=1.0*(will-depth+1)/A.calc();
    for(int i=x+1;tmp>i;++i)
    {
        score  C(1,i);
        if(A<C)continue;
        score tmp (1,i);
        score B=A-tmp;
        if(depth>1)s[++sr]=x;
        DFS(B,depth+1,i,will);
        if(depth>1)--sr;
    }
}
int main()
{
    int a,b;
    cin>>a>>b;
    score A(a,b);
    int cnt  = 0 ;
    while(1)
    {
        cnt++ ;
        DFS(A,1,1,cnt);
        if(cmp) {put();return 0;}
    }   
}

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值