zoukankan      html  css  js  c++  java
  • 洛谷-P2258 子矩阵

    子矩阵

    题目描述

    给出如下定义:

    1. 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵。

    例如,下面左图中选取第22、44行和第22、44、55列交叉位置的元素得到一个2 imes 32×3的子矩阵如右图所示。

    9 3 3 3 9

    9 4 8 7 4

    1 7 4 6 6

    6 8 5 6 9

    7 4 5 6 1

    的其中一个2 imes 32×3的子矩阵是

    4 7 4

    8 6 9

    1. 相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的。

    2. 矩阵的分值:矩阵中每一对相邻元素之差的绝对值之和。

    本题任务:给定一个n行m列的正整数矩阵,请你从这个矩阵中选出一个rc列的子矩阵,使得这个子矩阵的分值最小,并输出这个分值。

    题目链接:https://www.luogu.com.cn/problem/P2258

    解题思路:对行进行枚举(dfs确定选择哪些行,对列进行dp)通过dp求解即可

    • #include<bits/stdc++.h>
      using namespace std;
      const int maxn=60;
      const int inf=0x3f3f3f3f;
      int n,m,r,c,ans;
      int R[maxn],cost[maxn][maxn],dp[maxn][maxn],a[maxn][maxn],val[maxn];
      //R表示需要选择哪些行,cost表示选择两列所增加的分值
      //val表示选择列中增加的值,dp[i][j]表示前i列中选取j列所需要的能量值
      int getdp()
      {
          int res=inf;
          for(int i=1;i<=m;i++)
          {
              val[i]=0;
              for(int j=1;j<r;j++)
              {
                  val[i]+=abs(a[R[j]][i]-a[R[j+1]][i]);
              }
          }
          for(int i=1;i<=m;i++)
          {
              for(int j=i+1;j<=m;j++)
              {
                  cost[i][j]=0;
                  for(int k=1;k<=r;k++)
                  {
                      cost[i][j]+=abs(a[R[k]][i]-a[R[k]][j]);
                  }
              }
          }
          for(int i=1;i<=m;i++) //假设第i列已经选取,只需要dp前i-1列中选取j-1列所需要的最小值即可
          {
              for(int j=1;j<=i&&j<=c;j++)
              {
                  dp[i][j]=1e9;
                  for(int k=j-1;k<i;k++)
                    dp[i][j]=min(dp[i][j],dp[k][j-1]+cost[k][i]+val[i]);
              }
          }
          for(int i=c;i<=m;i++) res=min(res,dp[i][c]);
          return res;
      }
      void dfs(int now,int cnt)
      {
          if(now>n)
          {
              if(cnt==r) ans=min(ans,getdp());
              return ;
          }
          dfs(now+1,cnt);
          R[cnt+1]=now;
          dfs(now+1,cnt+1);
          return ;
      }
      int main()
      {
          cin>>n>>m>>r>>c;
           for(int i=1;i<=n;i++)
           {
               for(int j=1;j<=m;j++)
               {
                    cin>>a[i][j];
               }
      
           }
           ans=inf;
           dfs(1,0);
           cout<<ans<<endl;
           return 0;
      }
  • 相关阅读:
    Redis-cluster集群
    MySQL-binlog日志格式
    MySQL-备份与恢复
    PG-内存参数配置标准
    [POJ1724]Roads
    [POJ1062][最短路]昂贵的聘礼
    我的小博客美化记(仍在持续修改和增加,敬请持续关注)
    [离散化模板][并查集][洛谷1955]程序自动化分析
    python调用百度接口解析/逆解析地址
    datax安装部署
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/12038919.html
Copyright © 2011-2022 走看看