team2012-F3-sol-0004
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
题意:给定4个圆的圆心且限制4个圆无公共部分相交,求半径之和的最大值。
是一个线性规划问题:
最大化:x1 + x2 + x3 + x4
约束: x1 + x2 <= a1, x1 + x3 <= a2...共6个约束,且x1, x2, x3, x4 >= 0
即可以用单纯形算法解决。
}}}
{{{
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INFI = 1e20;
double mat[100][100];
int n, m, x[10], y[10];
double gao()
{
while(true)
{
int find = 0, col, row;
for(int i=1;i<=n;i++)
if(mat[m+1][i] > 0)
{
find = 1;
col = i;
break;
}
if(!find) return mat[m+1][n+1];
double min_i = INFI;
for(int i=1;i<=m;i++)
if(mat[i][col] > 0)
{
double t = mat[i][n+1]/mat[i][col];
if(min_i > t)
{
min_i = t;
row = i;
}
}
double tmp = mat[row][col];
for(int i=1;i<=n+1;i++)
mat[row][i] /= tmp;
mat[row][col] = 1/tmp;
for(int i=1;i<=m+1;i++)
if(row!=i)
{
for(int j=1;j<=n;j++)
if(col!=j)
mat[i][j] -= mat[i][col]*mat[row][j];
if(i==m+1)
mat[i][n+1] += mat[i][col]*mat[row][n+1];
else
mat[i][n+1] -= mat[i][col]*mat[row][n+1];
mat[i][col] = (-1)*mat[i][col]*mat[row][col];
}
}
}
double dis(int i, int j)
{
double dx = x[i]-x[j],
dy = y[i]-y[j];
return sqrt(dx*dx+dy*dy);
}
int main()
{
while(cin>>x[1]>>y[1])
{
for(int i=2;i<=4;i++)
cin>>x[i]>>y[i];
m = 0;
n = 4;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
m++;
for(int k=1;k<=n;k++)
if(k==i || k==j)
mat[m][k] = 1;
else
mat[m][k] = 0;
mat[m][n+1] = dis(i, j);
}
for(int i=1;i<=n;i++)
mat[m+1][i] = 1;
mat[m+1][n+1] = 0;
cout.precision(8);
cout<<fixed<<gao()<<endl;
}
return 0;
}
}}}
题意:给定4个圆的圆心且限制4个圆无公共部分相交,求半径之和的最大值。
是一个线性规划问题:
最大化:x1 + x2 + x3 + x4
约束: x1 + x2 <= a1, x1 + x3 <= a2...共6个约束,且x1, x2, x3, x4 >= 0
即可以用单纯形算法解决。
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INFI = 1e20;
double mat[100][100];
int n, m, x[10], y[10];
double gao()
{
while(true)
{
int find = 0, col, row;
for(int i=1;i<=n;i++)
if(mat[m+1][i] > 0)
{
find = 1;
col = i;
break;
}
if(!find) return mat[m+1][n+1];
double min_i = INFI;
for(int i=1;i<=m;i++)
if(mat[i][col] > 0)
{
double t = mat[i][n+1]/mat[i][col];
if(min_i > t)
{
min_i = t;
row = i;
}
}
double tmp = mat[row][col];
for(int i=1;i<=n+1;i++)
mat[row][i] /= tmp;
mat[row][col] = 1/tmp;
for(int i=1;i<=m+1;i++)
if(row!=i)
{
for(int j=1;j<=n;j++)
if(col!=j)
mat[i][j] -= mat[i][col]*mat[row][j];
if(i==m+1)
mat[i][n+1] += mat[i][col]*mat[row][n+1];
else
mat[i][n+1] -= mat[i][col]*mat[row][n+1];
mat[i][col] = (-1)*mat[i][col]*mat[row][col];
}
}
}
double dis(int i, int j)
{
double dx = x[i]-x[j],
dy = y[i]-y[j];
return sqrt(dx*dx+dy*dy);
}
int main()
{
while(cin>>x[1]>>y[1])
{
for(int i=2;i<=4;i++)
cin>>x[i]>>y[i];
m = 0;
n = 4;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
m++;
for(int k=1;k<=n;k++)
if(k==i || k==j)
mat[m][k] = 1;
else
mat[m][k] = 0;
mat[m][n+1] = dis(i, j);
}
for(int i=1;i<=n;i++)
mat[m+1][i] = 1;
mat[m+1][n+1] = 0;
cout.precision(8);
cout<<fixed<<gao()<<endl;
}
return 0;
}