【BZOJ3112】防守战线(ZJOI2013)-单纯形法+对偶理论

测试地址(题面在Discuss里):防守战线
做法:这题需要用到线性规划知识中的单纯形法和对偶理论。
观察题目,设每个位置建的塔数为 xi ,我们可以知道所有约束条件都可以表示成 Rii=LixiDi 的形式,我们把系数矩阵记作 A ,所有变量xi排成一个列向量 X ,那么这个线性规划可以写成:
目标函数:minCX,约束条件: AXB,X0
根据对偶理论,可以将问题转化成关于 Y 的对偶问题:
目标函数:maxBTY,约束条件: ATYCT,Y0
这样的话,两个问题的最优解是相等的,且能保证目标函数取最优解时各个变量为整数,所以我们只需用单纯形法解后面的问题即可。
以下是本人代码(TLE70分代码,更高超的卡常数技巧有待学习):

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define inf 1e9
#define eps 1e-8
using namespace std;
int n,m,p[10010];
double a[1010][10010]={0},tmp[10010];

void solve()
{
  while(1)
  {
    int k1,k2;
    double Max;
    memset(tmp,0,sizeof(tmp));
    memset(p,0,sizeof(p));

    for(int i=1;i<=m;i++)
      if (a[n+1][i]<0)
      {
        double Min=inf;
        for(int j=1;j<=n;j++)
          if (a[j][i]>0)
          {
            double t=a[j][m+1]/a[j][i];
            if (Min>t)
            {
              Min=t;
              p[i]=j;
            }
          }
        if (p[i]) tmp[i]=-a[p[i]][m+1]*a[n+1][i]/a[p[i]][i];
      }

    Max=0.0;
    for(int i=1;i<=m;i++)
      if (Max<tmp[i])
      {
        Max=tmp[i];
        k2=i;
      }
    if (fabs(Max)<eps) break;
    k1=p[k2];

    a[k1][k2]=1.0/a[k1][k2];
    for(int i=1;i<=m+1;i++)
      if (i!=k2) a[k1][i]*=a[k1][k2];
    for(int i=1;i<=n+1;i++)
      if (i!=k1)
      {
        for(int j=1;j<=m+1;j++)
          if (j!=k2) a[i][j]-=a[i][k2]*a[k1][j];
      }
    for(int i=1;i<=n+1;i++)
      if (i!=k1) a[i][k2]=-a[i][k2]*a[k1][k2];
  }
}

int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)
    scanf("%lf",&a[i][m+1]);
  for(int i=1;i<=m;i++)
  {
    int l,r;
    double d;
    scanf("%d%d%lf",&l,&r,&d);
    for(int j=l;j<=r;j++)
      a[j][i]=1;
    a[n+1][i]=-d;
  }
  solve();
  printf("%.0lf",a[n+1][m+1]);

  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值