您的位置:首页 > 其它

sdnu山东省ACM 2010年第一届省赛Greatest Number

2015-07-24 22:04 267 查看
原题链接:http://210.44.14.31/problem/show/1141

注意事项:

范围太大,爆搜超时。

本人猜测,本题的测试数据可能均是需要四个数才能的出最优解(依据第二个代码)。

具体分析看代码。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstdio>			//别用cin,本题测试数据较多
using namespace std;
int num[1000000 + 10];
int main()
{
int n, m;
int k = 0;
while (scanf_s("%d%d",&n,&m)&&(n||m))
{
num[0] = 0;
int max = 0;
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &num[i]);
if (num[i]>m)			//超范围的直接去除
{
n--;
i--;
continue;
}
}												//此时num数组里有 1到n 个单个的值
int cnt = n+1;
cout << "Case " << ++k << ": ";
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (num[i] + num[j]<=m)
num[cnt++] = num[i] + num[j];
//此时前n个位单个值,n+1到cnt为不大于m的所有两个值的和
sort(num, num + cnt);
int left, right=cnt-1,nextright=cnt-1;
for (int i = 0; i < cnt; i++)				//因为数组里有单个值也有两个值的和  所以会出现 两个值的和、三个值的和、四个值的和
{
left = i;
while (left <= right)
{
int mid = (left + right) >> 1;
int tempmax = num[i] + num[mid];
if ( tempmax< m)
{
left = mid + 1;

if ( tempmax> max)
{
max = tempmax;
nextright = mid;		//关键:在已经排好序的数组里,从i到i+1    i对应的mid必定在i+1对应的mid  的右边即mid(i)>=mid(i+1)这样做可以提高效率
}

}
else if (tempmax>m)
right = mid - 1;
else				//找到直接结束循环
{
max = m;
i = cnt;
break;
}
}
right = nextright;		//将right减小
}
cout << max << endl<<endl;
}
return 0;
}


附另解(本解法只用了四个数的组合便可ac,代码简单就不做详解了):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int str[1000010],op[1010];
int main()
{
int i,j,k,n,m,ans,t=1;
bool flag=false;
while(~scanf("%d%d",&n,&m),n||m)
{
op[0] = k = 0;
for(i=1;i<=n;i++)
scanf("%d",&op[i]);
sort(op,op+n+1);
for(i=0;i<=n;i++)
for(j=i;j<=n;j++)
{
if(op[i]+op[j]<=m)
str[k++] = op[i]+op[j];
}
sort(str,str+k);
ans = 0;
for(i=0;i<k;i++)
{
int low=i,high=k-1;
while(low<high)
{
int mid=(low+high)/2;
if(str[i]+str[mid]>m)
high = mid-1;
else
low = mid+1;
}
if(str[i]+str[low]>ans && str[i]+str[low]<=m)
ans = str[i]+str[low];
}
if(flag)
printf("\n");
printf("Case %d: %d\n",t++,ans);
flag = true;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: