• 【NOIP2014】子矩阵


    dfs+dp

    我们要在一个大矩阵中选出一个小矩阵使得小矩阵的分值最小

    所以我们先用dfs枚举选哪些行,再在dfs选的行的基础上对列进行dp,最后更新答案即可。

    具体地,我们先通过dfs枚举r行,然后计算两个数组:sum[i][j]表示在当前dfs确定的行的状态下,第i列和第j列相邻时产生的分值。s[i]表示在当前dfs确定的行的状态下,第i列选出r行后的分值。

    之后,我们对列进行一次dp,定义f[i][j]表示在当前dfs确定的行的状态下,前i列中选了j列(其中第i列选)的分值,那么状态转移方程很简单。

    所以我们就解决了这个问题。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 using namespace std;
     7 typedef long long ll;
     8 int n,m,r,c;
     9 inline int read() {
    10     int ret=0;
    11     int op=1;
    12     char c=getchar();
    13     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
    14     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
    15     return ret*op;
    16 }
    17 int a[20][20],ans=999999999;
    18 int f[20][20],now[20],sum[20][20],s[20];
    19 void calc() {
    20     memset(s,0,sizeof(s));
    21     memset(sum,0,sizeof(sum));
    22     for(int i=1;i<=m;i++)
    23         for(int j=2;j<=r;j++)
    24             s[i]+=abs(a[now[j]][i]-a[now[j-1]][i]);
    25     for(int i=1;i<=m;i++)
    26         for(int j=i+1;j<=m;j++)
    27             for(int k=1;k<=r;k++)
    28                 sum[i][j]+=abs(a[now[k]][i]-a[now[k]][j]);
    29 }
    30 int dp() {
    31     int ret=999999999;
    32     memset(f,0x3f,sizeof(f));
    33     for(int i=1;i<=m;i++) {
    34         f[i][1]=s[i];
    35         for(int j=2;j<=c;j++)
    36             for(int k=1;k<i;k++)
    37                 f[i][j]=min(f[i][j],f[k][j-1]+s[i]+sum[k][i]);
    38         ret=min(ret,f[i][c]);
    39     }
    40     return ret;
    41 }
    42 void dfs(int u) {
    43     if(u==r+1) {
    44         calc();
    45         ans=min(ans,dp());
    46         return ;
    47     }
    48     for(int i=now[u-1]+1;i<=n;i++) {
    49         now[u]=i;
    50         dfs(u+1);
    51         now[u]=0;
    52     }
    53 }
    54 int main() {
    55     n=read(); m=read(); r=read(); c=read();
    56     for(int i=1;i<=n;i++)
    57         for(int j=1;j<=m;j++)
    58             a[i][j]=read();
    59     dfs(1);
    60     printf("%d
    ",ans);
    61     return 0;
    62 }
    AC Code
  • 相关阅读:
    JS日期格式转换
    VMware虚拟化集群的配置(一)
    网络初级篇之STP(概念原理)
    运维学习篇之jenkins的安装(CentOS7)
    网络初级篇之配置telnet登录网络设备(实验)
    Linux操作篇之OpenKM的安装(汉化)
    网络初级篇之网络设备的FTP(原理与实验)
    网络初级篇之直连路由与静态路由(原理与实验)
    网络初级篇之DHCP原理与配置(原理与实验)
    网络初级篇之OSPF(二)实验
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11028874.html
Copyright © 2020-2023  润新知