zoukankan      html  css  js  c++  java
  • 拯救莫莉斯

    一道考试题:然而谁会想到我考试的时候打了一个最小费用最大流??

    真是弱爆了。。。

                拯救莫莉斯

                    时间限制: 1 Sec  内存限制: 256 MB

    题目描述

    问题描述

    莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场。

    圣域的地图可以看成是一个n*m的矩阵。每个整数坐标点(x , y)表示一座城市(1<=x<= n, 1<=y<=m)。两座城市间相邻的定义为:对于城市(Ax, Ay)和城市(Bx, By),满足(Ax - Bx)2 + (Ay - By)2 = 1。

    由于圣域的石油贸易总量很大,莫莉斯意识到不能让每笔石油订购单都从同一个油库里发货。为了提高效率,莫莉斯·乔决定在其中一些城市里建造油库,最终使得每一个城市X都满足下列条件之一:

    1.该城市X内建有油库,

    2.某城市Y内建有油库,且城市X与城市Y相邻。

    与地球类似,圣域里不同城市间的地价可能也会有所不同,所以莫莉斯想让完成目标的总花费尽可能少。如果存在多组方案,为了方便管理,莫莉斯会选择建造较少的油库个数。

    输入格式

    第一行两个正整数n,m ( n * m <= 50 且m<=n),表示矩阵的大小。

    接下来一个n行m列的矩阵F,Fi, j表示在城市(i,j)建造油库的代价。

    输出格式

    输出两个数,建造方案的油库个数和方案的总代价。

    输入样例:

    输出样例:

    3 3

    6 5 4

    1 2 3

    7 8 9

    3 6

    数据范围

    对于30%数据满足 n * m <= 25;

    对于100%数据满足n * m <= 50; 0 <= Fi, j <= 100000

    因为是考试题,一定要详细点::

      首先读到题时要认真审题,是n*m<=50!!当你真真正正的理解题了后,忽然发现,这就是个状压啊~

    设f[i][j][k]数组存储的是最小的花费,第一维代表前i行,第二维代表上一行的状态,第三维代表这一行的状态。

    预处理出cost[i][j]数组代表在第i行时选取状态j时的花费;

    所以很容易得出状态转移方程:f[i][k][u]=min(f[i][j][k]+cost[i][u]);

    经过严密的调查发现因为每一个城市至少要有一个油库与之相邻,所以这个状态能够转移过来的前提是(i | j | u | k<<1| k>>1)&(1<<m)-1==(1<<m)-1

    k代表当前这一行。这里一定要注意优先级!!

    因为转移到第n行时有两维状态不确定,所以我们转移到第n+1行;

    在转移f数组时同时维护一个g数组代表最小个数就好了!!

      希望下回能AC( ⊙ o ⊙ )啊!(来自蒟蒻的祈望~~)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int read(){
     7     int sum=0;char ch=getchar();
     8     while(ch<'0'||ch>'9') ch=getchar();
     9     while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    10     return sum;
    11 }
    12 int n,m;
    13 int v[52][52],cost[52][1<<8],sum[1<<8];
    14 int f[52][1<<8][1<<8],g[52][1<<8][1<<8];
    15 inline int get(int zt){
    16     int num;
    17     for(num=0;(1<<num)<=zt;++num);
    18     return num;
    19 }
    20 inline int get_sum(int zt){
    21     int num=0;
    22     while(zt){
    23         if(zt&1) num++;
    24         zt>>=1;
    25     }
    26     return num;
    27 }
    28 void St(){
    29     for(int i=1;i<=n;++i)
    30         for(int j=1;j<1<<m;++j){
    31             int p=get(j);
    32             cost[i][j]=cost[i][j^(1<<p-1)]+v[i][p];
    33         }
    34     for(int i=0;i<1<<m;++i)
    35         sum[i]=get_sum(i);
    36 }
    37 void Dp(){
    38     for(int i=0;i<1<<m;++i){
    39         f[1][0][i]=cost[1][i];
    40         g[1][0][i]=sum[i];
    41     }
    42     for(int i=1;i<=n;++i)
    43         for(int j=0;j<1<<m;++j)//上一列的状态
    44             for(int u=0;u<1<<m;++u){//这一列的状态
    45                 if(f[i][j][u]>100000000) continue;
    46                 for(int p=0;p<1<<m;++p)//下一列的状态
    47                     if(((j|u|p|(u>>1)|(u<<1))&((1<<m)-1))==((1<<m)-1)){
    48                         if(f[i+1][u][p]>=f[i][j][u]+cost[i+1][p]){
    49                             if(f[i+1][u][p]==f[i][j][u]+cost[i+1][p]){
    50                                 g[i+1][u][p]=min(g[i+1][u][p],g[i][j][u]+sum[p]);
    51                             }
    52                             else{
    53                                 f[i+1][u][p]=f[i][j][u]+cost[i+1][p];
    54                                 g[i+1][u][p]=g[i][j][u]+sum[p];
    55                             }
    56                         }
    57                     }
    58                 }
    59 }
    60 int main(){
    61     freopen("proj.in","r",stdin);
    62     freopen("proj.out","w",stdout);
    63     memset(f,0x3f,sizeof(f));
    64     n=read();m=read();
    65     for(int i=1;i<=n;++i)
    66         for(int j=1;j<=m;++j)
    67             v[i][j]=read();
    68     St();Dp();
    69     int ans=0x7fffffff,res=0x7fffffff;
    70     for(int i=0;i<1<<m;++i){
    71         if(ans>=f[n+1][i][0]){
    72             if(ans==f[n+1][i][0])
    73                 res=min(res,g[n+1][i][0]);
    74             else
    75                 res=g[n+1][i][0];
    76             ans=f[n+1][i][0];
    77         }
    78     }
    79     printf("%d %d
    ",res,ans);
    80     return 0;
    81 }

      

  • 相关阅读:
    用OpenStack界面轻松创建虚拟机的你,看得懂虚拟机启动的这24个参数么?
    Qemu,KVM,Virsh傻傻的分不清
    我是虚拟机内核我困惑?!
    不是技术也能看懂云计算,大数据,人工智能
    有了Openvswitch和Docker,终于可以做《TCP/IP详解》的实验了!
    FIO性能测试
    Python第三方打包库——PyInstaller
    Python函数和代码复用
    Python分支结构和循环结构
    Python基础随机数库——random
  • 原文地址:https://www.cnblogs.com/Maplers/p/7295772.html
Copyright © 2011-2022 走看看