做题过程:
分析了这道题的数据1e9,肯定要找到什么规律,于是就从理论上算了一下,在只有一张wild卡时,不可能加在中间牌上
加在最大值上:
加在最小值上:
当时,,即此时加在最大值上最优,否则加在最小值上。
当wild数大于1时,同样有次结论。
所以重点分析的情况,但是训练的时候没有分析出来。test通过最多的一次是所有的都加在最大值上算一次,所有的都加在最小的上算一次,然后取大的,wa在了30才想到加在最小的上后,最小的可能不再是最小的。
正确思路:
- 一种是:wild数大的时候,全部都加在最大牌数上最大,当wild数较小的时候,暴力所有的情况。即将整数d划分为3个非负整数再加在上。
- 另一种是我的思路的延续或者是升华,不过他是从最终结果开始推的,我觉得这种想法很值得学习。在时直接暴力最终的情况。此时源的值可以算出来,然后将分为最大值-最小值小于等于3的3个数,且满足这三个数都大于等于原来的数(如果是我绝对不会想到这一点)。大佬秀
交了后思路2时间31ms,思路1时间171ms,这就是思维的力量吧orz。
结论:
- 怼不出来规律就适当地暴力啊
- 从最终结果出发考虑问题
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
long long a[3],d;
LL b[3];
LL calc(LL a,LL b,LL c)
{
return a*a+b*b+c*c+7*min(min(b,c),a);
}
LL solve()
{
LL ans=0;
LL s=a[0]+a[1]+a[2]+d;
sort(a,a+3);
for(int i=0;i<=3;++i)
for(int j=0;j<=3;++j)
{
if(s-i-j>=0&&(s-i-j)%3==0)
{
b[0]=(s-i-j)/3;
b[1]=b[0]+i;
b[2]=b[0]+j;
sort(b,b+3);
if(b[0]>=a[0]&&b[1]>=a[1]&&b[2]>=a[2])
ans=max(calc(b[0],b[1],b[2]),ans);
}
}
return ans;
}
int main()
{
int n;
cin>>n;
while(n--)
{
cin>>a[0]>>a[1]>>a[2]>>d;
sort(a,a+3);
cout<<max(solve(),calc(a[2]+d,a[1],a[0]))<<endl;
}
return 0;
}