[BoundedOptimization TopCoder - 12294](https://vjudge.net/problem/TopCoder-12294)

BoundedOptimization TopCoder - 12294

考虑在最优情况下,某一些数在 \(\text{lowerbound}\) ,某一些在 \(\text{upperbound}\)

确定了这些数之后,对于那些处于 \((\text{lowerbound,upperbound})\) 之间的数,它们的值其实是在忽略了上下界的情况下能取到的最优情况

否则只要上下移动一点就可能达到一个更优的情况

那么考虑枚举每个数的状态在 \(\text{lowerbound,upperbound,(lowerbound,uppperbound)}\)

推论:在中间的数之间必然存在互相关系

假设存在两个数 \(x_i,x_j\) 之间没有互相关系,令其他数不变,

则答案式子可以表示为 \(ax_i+bx_j+c\) 的形式,改变两个数的值总能得到更优的情况

\[ \ \]

设处在中间位置的数为 \(x_1,\cdots,x_m\) ,其他数为 \(y_1,\cdots ,y_k\) ,每个数连到外面的权值总和为 \(s_i\)

发现在最优情况下, \(\sum x_i+\sum y_i =MaxSum\) ,那么就确定了 \(\sum x_i\) 的值,设为 \(Sum\)

那么答案就可以表示为 \(\begin{aligned}\frac{\sum_ix_i\cdot(Sum-x_i+2\cdot s_i)}{2}\end{aligned}+c\)

其中常数 \(c\) 是外面的数之间的总和

不考虑限制的情况下,最优情况是 \(x_i=\frac{Sum+s_i}{2}\)

此时,若 \(\sum x_i\ne Sum\) ,是不合法的,需要调整

而让每个数改变 \(d\) ,减少的答案都是 \(d^2\) (因为原来是在二次函数的最高点)

所以每个数都改变 \(\begin{aligned}\frac{\sum \frac{Sum+x_i}{2}-Sum}{m}\end{aligned}\) 是最优的

注意这里计算时都是忽略了 \(x_1,\cdots,x_m\)\(\text{lowerbound,upperbound}\) ,求出的值不一定合法

如果不合法说明至少有某个值该到上下界之后答案会更优,所以这次的答案不用考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef double db;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)

#define pb push_back
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }

const int N=30;
const db eps=1e-7;

int G[N][N];
int A[N],w[N];
db val[N];

class BoundedOptimization {
public:
double maxValue(vector <string> Expr, vector <int> L, vector <int> R, int Max) {
string E="";
for(string t:Expr) E+=t;
memset(G,0,sizeof G);
rep(i,0,E.size()-1) if(isalpha(E[i])) {
G[E[i]-'a'][E[i+1]-'a']=G[E[i+1]-'a'][E[i]-'a']=1;
i++;
}
int n=L.size();
db ans=0;
rep(S,0,pow(3,n)-1) {
int T=S,m=0;
db res=0,sum=0;
rep(i,0,n-1) {
w[i]=T%3;
if(!w[i]) A[++m]=i;
else val[i]=(w[i]==1?L[i]:R[i]),sum+=val[i];
T/=3;
}
int fl=sum<=Max;
rep(i,1,m) rep(j,i+1,m) if(!G[A[i]][A[j]]) fl=0;
if(!fl) continue;
db left=Max-sum;
rep(i,1,m) {
db c=left;
rep(j,0,n-1) if(w[j] && G[A[i]][j]) c+=val[j]*2;
val[A[i]]=c/2;
sum+=val[A[i]];
}
if(m){
db t=(sum-Max)/m;
rep(i,1,m) val[A[i]]-=t;
}
rep(i,0,n-1) if(val[i]<L[i]-eps || val[i]>R[i]+eps) fl=0;
if(!fl) continue;
rep(i,0,n-1) rep(j,i+1,n-1) if(G[i][j]) res+=val[i]*val[j];
cmax(ans,res);
}
return ans;
}
};