• 题解:子矩阵(NOIP2014普及组T4)


    又是dp

    暴力枚举会T

    考虑先固定一个变量,比如先枚举行

    然后预处理每行之间的绝对值,每列之间的绝对值

    然后dp进行转移

    注意记录选择的行数

    转移记得加上新选的列的行之间的绝对值,即w[i],

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 using namespace std;
     6 int n, m, r, c;
     7 int a[20][20], f[20][20];//f[i][j]表示选择了i列,最后一列为j
     8 int w[20], v[20][20], path[20];
     9 int ans=1<<30;
    10 void work(){
    11     memset(f,127,sizeof(f));
    12     memset(w,0,sizeof(w));
    13     memset(v,0,sizeof(v)); 
    14     for(int i=1; i<=m; i++) 
    15         for(int j=1; j<r; j++) 
    16             w[i]+=abs(a[path[j]][i]-a[path[j+1]][i]); //记录已选择的行之间第i列的绝对值
    17     for(int i=1; i<=m; i++) 
    18         for(int j=i+1; j<=m; j++) 
    19             for(int k=1; k<=r; k++) 
    20                 v[i][j]+=abs(a[path[k]][i]-a[path[k]][j]); //预处理每列之间的绝对值差
    21     f[0][0]=0; 
    22     for(int i=1; i<=c; i++) 
    23         for(int j=i; j<=m; j++) 
    24             for(int k=0; k<j; k++) 
    25                 f[i][j]=min(f[i][j], f[i-1][k]+w[j]+v[k][j]);//dp
    26     for(int i=c; i<=m; i++) ans=min(ans, f[c][i]); //寻找答案
    27 
    28 }
    29 void dfs(int now, int pre){
    30     if(now>r){
    31         work();
    32         return ;
    33     }
    34     for(int i=pre+1; n-i>=r-now; i++){
    35         path[now]=i;
    36         dfs(now+1, i);
    37     }
    38 }
    39 int main(){
    40     scanf("%d%d%d%d",&n,&m,&r,&c);
    41     for(int i=1; i<=n; ++i)
    42         for(int j=1; j<=m; ++j)
    43             scanf("%d",&a[i][j]);
    44     dfs(1, 0);
    45     cout<<ans<<endl;
    46     return 0;
    47 }
  • 相关阅读:
    顧客満足度調査
    GeoStTool.dll过滤图层
    GeoStTool.ini相关技术要点
    GeoStTool.dll与RasterServer通信
    hdu 1007 Quoit Design
    hdu 4325 Flowers
    hdu 2516 取石子游戏
    hdu 1006 Tick and Tick
    CodeForces 101A Homework
    ZOJ Problem Set 1879
  • 原文地址:https://www.cnblogs.com/Aze-qwq/p/9879711.html
Copyright © 2020-2023  润新知