您的位置:首页 > 其它

uva12558 (迭代加深搜索)

2016-07-29 13:24 218 查看
题目链接

题意:对一个分数(n/m)将它分解成若干个不相等的单分子分数(即分子为1)。求最少能分解成哪几个分数相加。若有多解,输出最大的分母尽量的小的解。会有k个禁止使用的单分子分数。

思路:这题搜索的特点就是深度和宽度都不确定,首先对于一个a/b,你不知道他的最优解有几个1/a类似形式的分数构成,这是宽度。对于每个1/i他的深度也是不确定的,唯一剪枝的条件就是确定深度后余下都选择1/i之和小于a/b。

详细过程见编码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100000+10;
set<ll>ban;
int maxed;
bool ok;
ll v[maxn],ans[maxn];
ll gcd(ll a,ll b) {return b==0 ?  a : gcd(b,a%b);}//求两个数最大公约数
ll get_first(ll a,ll b){return b/a+1;}//求比a/b小的最大的分子为一的分数

bool better(int d){//判断当前解比答案更满足题意
for(int i=d;i>=0;i--){
if(ans[i]!=v[i]){
return ans[i]==-1||v[i]<ans[i];
}
}
return false;
}

void dfs(int cur,ll from,ll a, ll b){//当前深度为cur,起点from开始搜和为a/b的解
if(cur==maxed){
if(b%a||ban.count(b/a)) return;
v[cur]=b;
if(better(cur)) memcpy(ans,v,sizeof(ll)*(cur+1));
ok=true;
return;
}
from=max(from,get_first(a,b));
for(int i=from;;i++){
if(a*i>=b*(maxed-cur+1)) return;//如果剩下的解都是1/i还小于a/b那就说明不满足
if(ban.count(i)) continue;
v[cur]=i;
ll t1=a*i-b,t2=b*i;//约分求新的剩下
ll g=gcd(t1,t2);
dfs(cur+1,i+1,t1/g,t2/g);
}
return;
}

int main()
{
int T,t=1;scanf("%d",&T);
while(T--){
ban.clear();
ll a,b;int n;
scanf("%lld %lld %d",&a,&b,&n);
for(int i=0;i<n;i++){
ll x;scanf("%lld",&x);ban.insert(x);
}
ok=false;
for(maxed=1;;maxed++){
memset(ans,-1,sizeof(ans));
dfs(0,get_first(a,b),a,b);
if(ok) break;
}
printf("Case %d: %lld/%lld=",t++,a,b);
printf("1/%lld",ans[0]);
for(int i=1;i<=maxed;i++) printf("+1/%lld",ans[i]);
puts("");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  迭代 搜索