题目链接:sicily 1047
解题思路:
题意很简单,即需要把一串连续的不超过25个的整数分成A、B两部分,分别相加得到两个数sumA、sumB,使得a+sumA=b+sumB。
一眼看过是感觉是0-1背包,但是其实不太一样,因为所有的整数是连续的,所以可以有更方便的方法解决。
假设第一个数为low,最后一个数为high,我们可以得到如下定理:
当A部分有 i 个数时,当且仅当(low+low+i-1)*i/2 <= sumA <= (high+high-i+1)*i/2时,存在满足题意的组合。
于是我们的算法就是枚举A部分有不同个数时,检查不等式组是否被满足。注意首先需要判断a+sumA+b+sumB是否为偶数,并且sumA与sumB不能为负数,详见代码。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int a,b,low,high;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d %d",&a,&b,&low,&high);
if(b<a){
swap(a,b);
}
int flag=0,sum=a+b,tmp;
sum += (low+high)*(high-low+1)/2;
tmp = sum/2;
if(sum%2==0&&tmp>=a)
{
tmp -= a;
for(int i=0;i<=high-low+1;i++)
{
int low_val = (low+low+i-1)*i/2, high_val = (high+high-i+1)*i/2;
if(tmp>=low_val&&tmp<=high_val){
flag=1;
break;
}
}
}
if(flag)
printf("possible\n");
else
printf("not possible\n");
}
return 0;
}
总结:
好题!懂得复杂算法之后不能忽视问题中的数学属性。