zoukankan      html  css  js  c++  java
  • 矩阵消除游戏(状压)

    链接:https://ac.nowcoder.com/acm/problem/200190
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

    牛妹在玩一个名为矩阵消除的游戏,矩阵的大小是n行m列,第i行第j列的单元格的权值为ai,j,牛妹可以进行k个回合的游戏,在每个回合,牛妹可以选择一行或者选择一列,然后将这一行或者这一列的所有单元格中的权值变为0,同时牛妹的分数会加上这一行或者这一列中的所有单元格的权值的和。

    牛妹想最大化她的得分,球球你帮帮她吧!

    输入描述:

    第一行三个整数n,m,k
    接下来n行每行m个整数表示矩阵中各个单元格的权值。

    输出描述:

    输出一个整数表示牛妹能获得的最大分数。

    示例1

    输入

    3 3 2
    101 1 102
    1 202 1
    100 8 100

    输出

    414

    备注:

    1n,m15
    1ai,j1e6
    1knm

    首先考虑贪心,如果每次贪心地选矩阵中剩下的最大的一行或者一列,然后把这一行(列)抹为0可以吗?

    其实这样是不可取的,每次贪心选最大的是会影响后面的选取,局部最优解无法得到全局最优解,所以我们还是要枚举情况

    由1n,m15,暗示可以状压,直接状压走起

    直接看代码吧,注释很详细了(要有位运算基础)

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 #define pb push_back
     4 #define mst(a) memset(a,0,sizeof(a))
     5 const int INF = 0x3f3f3f3f;
     6 const double eps = 1e-8;
     7 const int mod = 1e9+7;
     8 const int maxn = 1e6+10;
     9 using namespace std;
    10 
    11 int G[20][20];
    12 int line[20];  //一行上的总值
    13 int col[20];  //一列上的总值
    14 
    15 int main()
    16 {
    17     #ifdef DEBUG
    18     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
    19     #endif
    20     
    21     int n,m,k;
    22     scanf("%d %d %d",&n,&m,&k);
    23     for(int i=1;i<=n;i++) //输入
    24     {
    25         for(int j=1;j<=m;j++)
    26         {
    27             scanf("%d",&G[i][j]);
    28             line[i] += G[i][j];
    29         }
    30     }
    31     k = min(k,min(n,m));  //当k大于min(n,m)时可以全取完
    32     LL ans = 0;
    33     for(int i=0;i<=(1<<n)-1;i++)
    34     {
    35         int numl = __builtin_popcount(i);  //通过i中有多少个1判断取了多少行
    36         int numc = k-numl;  //计算要取多少列
    37         if(numc>m||numc<0) continue;  //直接continue掉不可取的情况,numc>m(不够贪),numc<0(不可能)
    38 
    39         LL sum = 0;
    40         mst(col);  //不清数组试试
    41         for(int j=0;j<n;j++)  //遍历每一行
    42         {
    43             int flag = 0;  //判断该行取没取
    44             if((1<<j)&i) flag = 1;
    45             if(flag) sum += line[j+1];  //取该行
    46             for(int h=1;h<=m;h++)  //遍历每一列
    47                 if(!flag) col[h] += G[j+1][h];  //如果没取该行,就把该行的数加到对应的列col中
    48         }
    49         sort(col+1,col+1+m);  //按col值排序
    50         for(int j=m;numc>0;j--,numc--)  //先取col值大的,取numc个
    51             sum += col[j];
    52         ans = max(ans,sum);  //更新ans
    53     }
    54     printf("%lld
    ",ans);
    55     
    56     return 0;
    57 }

    -

  • 相关阅读:
    uva 10369 Arctic Network
    uvalive 5834 Genghis Khan The Conqueror
    uvalive 4848 Tour Belt
    uvalive 4960 Sensor Network
    codeforces 798c Mike And Gcd Problem
    codeforces 796c Bank Hacking
    codeforces 768c Jon Snow And His Favourite Number
    hdu 1114 Piggy-Bank
    poj 1276 Cash Machine
    bzoj 2423 最长公共子序列
  • 原文地址:https://www.cnblogs.com/jiamian/p/13200908.html
Copyright © 2011-2022 走看看