zoukankan      html  css  js  c++  java
  • 【UVa10498】Happiness-线性规划:单纯形法

    测试地址:Happiness
    题目大意:N种食品和M个人,每种食品都有一个价格(每单位pi),每个人对每种食品都有一个满意度,一个人的总满意度是他得到的食品量一一乘上对应的满意度,每个人也有一个满意度上限,总满意度不能超过这个上限,规定每个人得到的食品量都必须一一相同,问最多能花掉多少钱,答案向上取整
    做法:这一道题需要使用单纯形法解线性规划。
    将每个人得到的第i种食品量设为xi,那么所有的约束条件都可以表示成aixibi的形式,同时所有的xi都非负,我们要使得Mpixi最大,那么这显然就是一个线性规划的问题,把pixi当做目标函数求即可,使用单纯形法即可,这一题的约束条件已经是标准形式了,所以只要松弛变量,初始基本可行解就直接可以找出来了,而且这一题也不用判断无界情况,具体的步骤可以去网上查查资料,这里就不赘述了。注意答案要向上取整。
    一种优化方法:使用单纯形法来换基的时候,可以贪心使得每一次转轴变换后目标函数尽可能大,这样时间会得到显著优化。
    犯二的地方:理解错题目,以为线性规划的解就是最后的答案,结果还要乘M……
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #define eps 1e-8
    #define inf 1e9
    using namespace std;
    int n,m,p[51];
    double matrix[51][51],tmp[51];
    
    void solve()
    {
      while(1)
      {
        int k1,k2;
        double mx;
        memset(tmp,0,sizeof(tmp));
        memset(p,0,sizeof(p));
    
        for(int i=1;i<=n;i++)
          if (matrix[m+1][i]<0)
          {
            double Min=inf;
            for(int j=1;j<=m;j++)
              if (matrix[j][i]>0)
              {
                double t=matrix[j][n+1]/matrix[j][i];
                if (Min>t)
                {
                  Min=t;
                  p[i]=j;
                }
              }
            if (p[i]) tmp[i]=-matrix[m+1][i]*matrix[p[i]][n+1]/matrix[p[i]][i];
          }
    
        mx=0.0;
        for(int i=1;i<=n;i++)
          if (tmp[i]>mx) mx=tmp[i],k2=i;
        if (fabs(mx)<eps) break;
        k1=p[k2];
        //贪心
    
        matrix[k1][k2]=1.0/matrix[k1][k2];
        for(int i=1;i<=n+1;i++)
          if (i!=k2) matrix[k1][i]*=matrix[k1][k2];
        for(int i=1;i<=m+1;i++)
          if (i!=k1)
          {
            for(int j=1;j<=n+1;j++)
              if (j!=k2) matrix[i][j]-=matrix[k1][j]*matrix[i][k2];
          }
        for(int i=1;i<=m+1;i++)
          if (i!=k1) matrix[i][k2]=-matrix[i][k2]*matrix[k1][k2];
        //转轴变换
      }
    }
    
    int main()
    {
      while(scanf("%d%d",&n,&m)!=EOF)
      {
        memset(matrix,0,sizeof(matrix));
        for(int i=1;i<=n;i++)
        {
          scanf("%lf",&matrix[m+1][i]);
          matrix[m+1][i]=-matrix[m+1][i];
        }
        for(int i=1;i<=m;i++)
          for(int j=1;j<=n+1;j++)
            scanf("%lf",&matrix[i][j]);
        solve();
        int ans=(int)(matrix[m+1][n+1]*m);
        if (matrix[m+1][n+1]*m>ans) ans++;
        printf("Nasa can spend %d taka.
    ",ans);
      }
    
      return 0;
    }
    
  • 相关阅读:
    浅谈均值、方差、标准差、协方差的概念及意义
    数据库设计的基本步骤
    VS添加lib库
    Android activity_main.xml删除边缘距离,充满屏幕
    Android 设置旋转朝向
    WebStorm注册码
    VS禁止特定警告
    VS 高亮显示不带后缀的C++头文件
    VS2010设置C++包含目录和库目录
    读取STL模型
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793637.html
Copyright © 2011-2022 走看看