UVA12558
wanggiaoxing · · 题解
这道题是迭代加深,里面一些细节是很恶心的(例如 uva 输出)。
输出要多输出个空行!!!
其次我们来看这个题中并未提到枚举的长度,所以我们要自己枚举。思路大概就是枚举分母然后深搜,如果搜到与当前最好答案对比更新。迭代加深属于 dfs 又看了看这个数据,剪枝是难免的。
上下界剪枝
如果当前分数在之后的地方全选他(因为这个序列是单调递减的)都小于目前剩余的分数(那你废了呀)。
两个小细节
利用数据范围
题中说了不能出现的分母小于1000,所以我们判断时用数组就 ok 没必要 map 或 set (T到起飞)详情见代码。
判断 return 时
往常的判断都是如果当前层数是 dep+1 就 return 等等,但这样会浪费掉大量时间我们直接判断一样见代码。
#include<bits/stdc++.h>
using namespace std;
long long int n,v[200],dep,ans[200],s1[200];
bool p[1001];
bool flag;
bool find()//判断是否最优
{
for(long long i=dep;i>0;i--)
if (!ans[i])
return 1;
else
if(ans[i]!=s1[i])
return s1[i]<ans[i];
return 0;
}
//s是层数,la是剩余的分子,lb是剩余的分母
void dfs(long long int s,long long int la,long long int lb)
{
if(s==dep)//第2个小细节
{
if(lb%la==0&&(lb>1000||(lb<=1000&&p[lb/la]==0)))//第1个小细节
{
s1[s]=lb/la;
if(find())
memcpy(ans,s1,sizeof(s1));//更新
flag=1;
}
return;
}
for(long long int i=max(s1[s-1]+1,lb/la+1);lb*(dep-s+1)>la*i;i++)//for循环的条件即为剪枝
{
if(i<=1000&&p[i]==1)continue;
s1[s]=i;
long long int nb=lb*i;
long long int na=la*i-lb;
long long int j=__gcd(nb,na);//化简
dfs(s+1,na/j,nb/j);
}
}
int main()
{
cin>>n;
int a,b,c;
int y=1;
while(n--)
{
cin>>a>>b>>c;
flag=0;
memset(ans,0,sizeof(ans));
memset(p,0,sizeof(p));//初始化
for(int i=1;i<=c;i++)
cin>>v[i],p[v[i]]=1;
for(dep=2; ;dep++)
{
memset(s1,0,sizeof(s1));
s1[0]=a/b;//一个小小小小的细节
dfs(1,a,b);
if(flag==1)
{
cout<<"Case "<<y++<<": "<<a<<"/"<<b<<"=";
for(int i=1;i<dep;i++)
cout<<1<<"/"<<ans[i]<<"+";
cout<<1<<"/"<<ans[dep]<<endl;//输出
break;
}
}
}
return 0;
}