bzoj1538 [NWERC2017]High Score

网上的题解都很奇怪。。

经过相当长时间的思考,有了一个有效(自认为)的解法

设某一种合法分配方案完成后三个数分别变为a,b,c,其中a>=c,b>=c

此时如果让c减1,让a或b加1(设让t加了1),那么答案增加的值为2t+1-2c+1-7=2t-2c-5

令其>0,则t-c>2.5

由于t,c是整数,因此t-c>=3

也就是说,如果这种方案中最大值-最小值>=3,且最小值还能变得更小,那么一定存在一种更优方案(就是让c减1,让最大数加1后得到的方案),也就是说它一定不是最优方案

那么只需要考虑两种可能的最优方案:

1.最小值不能变得更小了;此时显然最优方案是把d全部加到三个数中最大数上

2.最大值-最小值<3;此时只要枚举最大值-最小值和次大值-最小值,然后O(1)求出答案的3个数并验证即可

A掉了。。。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 //#include<cassert>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef long long ll;
12 typedef unsigned long long ull;
13 typedef pair<int,int> pii;
14 ll calc(ll a,ll b,ll c)
15 {
16     return a*a+b*b+c*c+7*min(a,min(b,c));
17 }
18 vector<ll> p,q;
19 ll solve(ll a,ll b,ll c,ll d)
20 {
21     ll i,j,s=c+a+b+d,an=-0x3f3f3f3f;
22     q.clear();q.pb(a);q.pb(b);q.pb(c);
23     sort(q.begin(),q.end());
24     for(i=0;i<=2;i++)
25     {
26         for(j=0;j<=2;j++)
27         {
28             if(s-i-j>=0&&(s-i-j)%3==0)
29             {
30                 p.clear();
31                 p.pb((s-i-j)/3);
32                 p.pb(p[0]+i);p.pb(p[0]+j);
33                 sort(p.begin(),p.end());
34                 if(p[0]>=q[0]&&p[1]>=q[1]&&p[2]>=q[2])
35                 {
36                     an=max(an,calc(p[0],p[1],p[2]));
37                 }
38             }
39         }
40     }
41     return an;
42 }
43 ll T,a,b,c,d;
44 int main()
45 {
46     //freopen("/tmp/1538/1.in","r",stdin);
47     //freopen("/tmp/1538/1.ans","w",stdout);
48     scanf("%lld",&T);//assert(3<=T&&T<=7);
49     while(T--)
50     {
51         scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
52         p.clear();p.pb(a);p.pb(b);p.pb(c);
53         sort(p.begin(),p.end());
54         ll a1=calc(p[0],p[1],p[2]+d);
55         printf("%lld\n",max(a1,solve(a,b,c,d)));
56     }
57     return 0;
58 }

 

posted @ 2018-08-26 18:39  hehe_54321  阅读(211)  评论(0编辑  收藏  举报
AmazingCounters.com