可以枚举每个元素的值是上界、下界还是中间值,总共有 3n 3 n 种情况
若存在两个元素 xi,xj x i , x j ,它们都取中间值,且 xixj x i x j 不在式子中,
那么设表达式为 axi+bxj+c a x i + b x j + c ,可以发现最有情况肯定是 xi x i 或 xj x j 达到边界值
设 k k 为取中间值的元素的个数
所以表达式可以写作 其中 xi x i 为取中间值的元素
化一下式子得到
令 S=∑ki=1ai S = ∑ i = 1 k a i
也就是说 xi x i 取 S+2ai2 S + 2 a i 2 最优
但是这样 ∑xi ∑ x i 可能大于 S S ,所以要减小 ,设 bi b i 为 xi x i 要减去的数
则要最小化 ∑(S+2ai)24−(S+2ai2−bi)(S+2ai2+bi) ∑ ( S + 2 a i ) 2 4 − ( S + 2 a i 2 − b i ) ( S + 2 a i 2 + b i )
也就是 ∑b2i ∑ b i 2 ,当 bi b i 全相同的时候取最小值
所以 xi x i 减去 (∑xi−S)k ( ∑ x i − S ) k 就好了
算出 xi x i 后带入表达式计算一下就好了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N=20;
int n,l[N],r[N],a[N][N],vis[30],w[N],S;
double ans,val[N];
inline void calc(){
double rst=S;
for(int i=1;i<=n;i++) val[i]=0;
for(int i=1;i<=n;i++){
if(!w[i]) continue;
if(w[i]==1) val[i]=l[i],rst-=l[i];
else val[i]=r[i],rst-=r[i];
}
if(rst<0) return ;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(!w[i] && !w[j] && !a[i][j]) return ;
double tot=0; int cnt=0;
for(int i=1;i<=n;i++){
if(w[i]) continue;
double cur=0; cnt++;
for(int j=1;j<=n;j++)
if(w[j] && a[i][j]) cur+=val[j];
val[i]=cur+rst/2;
tot+=val[i];
}
if(cnt){
double k=(tot-rst)/cnt;
for(int i=1;i<=n;i++)
if(!w[i]) val[i]-=k;
}
for(int i=1;i<=n;i++)
if(val[i]+1e-7<l[i] || val[i]-1e-7>r[i]) return ;
double cans=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i][j]) cans+=val[i]*val[j];
ans=max(ans,cans);
}
void dfs(int x){
if(x>n) return calc();
for(int i=0;i<3;i++){
w[x]=i; dfs(x+1);
}
}
class BoundedOptimization{
public:
double maxValue(vector<string> expr,vector<int> lb,vector<int> rb,int maxS){
n=lb.size(); S=maxS;
for(int i=1;i<=n;i++) l[i]=lb[i-1],r[i]=rb[i-1];
string cur;
for(int i=0;i<expr.size();i++) cur+=expr[i];
for(int i=0;i<cur.size();i+=3){
a[cur[i]-'a'+1][cur[i+1]-'a'+1]=a[cur[i+1]-'a'+1][cur[i]-'a'+1]=1;
}
dfs(1);
return ans;
}
}Main;
int main(){
vector<string> a={ "ca+fc+fa+d", "b+da+", "dc+c", "b", "+ed+eb+ea" };
vector<int> lb= { 10, 11, 12, 13, 14, 15 },rb= { 15, 16, 17, 18, 19, 20 };
int mS=85;
printf("%.9lf\b",Main.maxValue(a,lb,rb,mS));
for(;;);
}