考虑在最优情况下,某一些数在$\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}$,求出的值不一定合法
如果不合法说明至少有某个值该到上下界之后答案会更优,所以这次的答案不用考虑
| 12
 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;
 }
 };
 
 
 |