http://http://codeforces.com/contest/550/problem/B
题意:
输入n,l,r,x以及n个数
在这n个数中找出i(i>=2 && i<=n)个数,使得它们的和>=l&&<=r,且最大值和最小值之差>=x
解题思路:
用dfs一个一个搜过去,下面这个代码是有缺陷的,如果一串数是a,b,c,d(由大到小),当sum=a+b+c大于r时,它仍会继续算sum=a+b+d,费时,但由于n最大是15,不会超时,仍能ac
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <math.h>
#include <algorithm>
using namespace std;
__int64 c[20],dp[20][20];
int ans;
__int64 n,l,r,x;
void dfs(__int64 sum, int a, int li, int an)
{
if(sum>=l && sum<=r && a>=x) ans++;
if(sum>r) return;
for(int i=li;i<=n;i++)
{
dfs(sum+c[i], c[i]-an, i+1, an);//an用来记录最小的那个值
}
}
int main()
{
cin>>n>>l>>r>>x;
for(int i=1;i<=n;i++)
{
cin>>c[i];
}
ans=0;
sort(c+1,c+n+1);
for(int i=1;i<n;i++)
dfs(c[i],0,i+1,c[i]);
cout<<ans<<endl;
return 0;
}
换一种思路,从两头开始,不断的向中间加,可避免上面讲的缺陷
#include <iostream>
#include <algorithm>
using namespace std;
int c[20];
__int64 n,l,r,x;
__int64 ans;
void dfs(int li, int ri, __int64 sum, int flag)
{
if(flag==0 && sum>=l && sum<=r) ans++;
if(sum>r) return;
if(li>ri) return;
dfs(li+1, ri, sum+c[li], 0);
dfs(li+1, ri, sum, 1);
}
int main()
{
cin>>n>>l>>r>>x;
for(int i=1;i<=n;i++)
{
cin>>c[i];
}
sort(c+1,c+1+n);
ans=0;
for(int i=1;i<=n;i++)
{
for(int j=n;j>i;j--)
{
if(c[i]+c[j]>r) continue;
if(c[j]-c[i]<x) break;
if(i+1==j)
{
if(c[i]+c[j]>=l) ans++;
continue;
}
dfs(i+1, j-1, c[i]+c[j], 0);
}
}
cout<<ans<<endl;
return 0;
}

本文解析了CodeForces竞赛中一道题目B的两种解题思路。第一种使用深度优先搜索(DFS)策略,虽然存在一定的冗余计算,但在限制条件下仍然能够得到正确答案;第二种方法则采用两端逼近的方法,通过不断向中间加数来有效避免冗余计算,提高效率。
1091

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



