题目:
题解:
似曾相识。。。似乎是很久以前loli的胡策题。。。
直接暴力肯定不行啊,这时候我们考虑减减枝
首先就是dfs的范围,如果我们迭代出来的长度为x的话,因为分子是1,那分母最大可以达到的范围就是 [1,⌈bxa⌉] ,我们只需要循环这一部分
其次就是分数的变化,我们可以搜出来一个减一个,那就是 ab−1i=ai−bbi
事实上我们并不需要搜到最后(分值变成0),因为最后一个肯定很大啊,那么如果只剩下最后一个了,而且分子为1,分母恰好还没遍历到的话,直接采取
搜着搜着你以前搜过的最大值已经小于你现在所在的分母的话,就没必要往下搜了吧
最后不要忘记对于dfs过程中的A,B开longlong,因为虽然一开始给的都是<=1000,但是你减来减去的即使是约分了也很大啊!
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 1e9
#define LL long long
using namespace std;
int a[1005],b[1005];LL maxx=INF,A,B;
bool vv=0;
int gcd(LL a,LL b){if (!b) return a;else return gcd(b,a%b);}
void yf(LL &a,LL &b)
{
int l=gcd(a,b);
a/=l;b/=l;
}
void dfs(int t,int last,int n,LL A,LL B)
{
yf(A,B);
if (n==1)
{
if (A==1 && B>last && maxx>B)
{
for (int i=1;i<t;i++)
a[i]=b[i];
a[t]=B;
maxx=a[t];
vv=1;
}
return;
}
if (maxx<last+1) return;
for (int i=last+1;i<=(int)ceil((double)(B*n)/A);i++)
{
b[t]=i;
dfs(t+1,i,n-1,A*i-B,B*i);
}
}
int main()
{
int i,j;
scanf("%d%d",&A,&B);
for (i=1;i<=1000;i++)
{
dfs(1,1,i,A,B);
if (vv)
{
for (j=1;j<=i;j++)
printf("%d ",a[j]);
return 0;
}
}
}
本文介绍了一种针对分数型搜索问题的优化方案,通过限制DFS的搜索范围和利用分数变化特性进行减枝,显著提高了搜索效率。适用于初始值不大于1000的分数搜索场景。
1734

被折叠的 条评论
为什么被折叠?



