P2258 sub-matrix solution to a problem []

Subject to the effect

Solution [NOIP2014 popularity] submatrix

Title effect: a matrix is defined as the absolute value of the difference value of two adjacent elements, in a test \ (n-\) OK \ (m \) matrix selected from a column \ (R & lt \) line \ ( C \) sub-matrix (i.e., the position of the cross element row) of the columns, so the minimum value

Topic Analysis: This question would like to get a start burst is found, but the analysis of what time complexity \ (O (C_n ^ rC_m ^ c) \) for fear that he found jeopardy meaning of the questions. \ (Dp \) ? , four-dimensional \ (dp \) can not writeNext leave

Then there is a magical practice, the first \ (dfs \) gold held, then we will get a lot of \ (r \) line \ (m \) columns of the matrix, and then use a two-dimensional \ (dp \) Solving

Set \ (f [i] [j ] \) represents the former \ (I \) column, this has been elected \ (J \) minimum score column Let \ (w [i] \) represents \ (I \ ) score in this column, \ (v [i] [J] \) represents \ (i, j \) scores two columns, then

\[f[i][j] = min\{f[k][j - 1] + w[i] + v[k][i] \quad | \quad j - 1 \leq k < i\}\]

Handled by some skills can not complex \ (if \) statement to consider boundary conditions, so that the program more concise. That is assuming that there is a virtual first (0 \) \ column

Analyze the complexity? Enumerate behavior \ (O (C_n ^ r) \) , once \ (dp \) the cost of \ (O (m ^ 2) \)

Therefore, the total complexity is \ (O (C_n ^ RM ^ 2) \) , run past (I constant have so explosive it, the mouthpiece oxygen running time becomes the original \ (\ frac {1} { 4} \) )

Code offer

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 32;
int n,m,r,c,p[maxn],w[maxn],v[maxn][maxn],f[maxn][maxn],val[maxn][maxn],ans = 1e9;
inline void dp(){//进行dp
    for(int i = 1;i <= m;i++)//初始化
        for(int j = 1;j <= m;j++)
            f[i][j] = 1e9;
    for(int i = 1;i <= m;i++){//计算每一列的分值
        w[i] = 0;
        for(int j = 2;j <= r;j++)
            w[i] += abs(val[p[j]][i] - val[p[j - 1]][i]);
    }
    for(int i = 1;i <= m;i++)//初始化
        for(int j = 1;j <= m;j++)
            v[i][j] = 0;
    for(int i = 1;i <= m;i++)//计算两两列之间的分值
        for(int j = 1;j <= m;j++)
            for(int k = 1;k <= r;k++)
                v[i][j] += abs(val[p[k]][i] - val[p[k]][j]);
    for(int i = 1;i <= m;i++)//进行dp
        for(int j = 1;j <= min(i,c);j++){
            for(int k = j - 1;k < i;k++)
                    f[i][j] = min(f[i][j],f[k][j - 1] + w[i] + v[k][i]);
            if(j == c)ans = min(ans,f[i][j]);//如果已经选了r行c列了,更新答案
        }
}
inline void dfs(int line,int step){//dfs枚举行
    if(step == r + 1){
        dp();
        return;
    }
    if(line > n)return;
    p[step] = line;
    dfs(line + 1,step + 1);
    dfs(line + 1,step);
}
int main(){
    scanf("%d %d %d %d",&n,&m,&r,&c);
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= m;j++)
            scanf("%d",&val[i][j]);
    dfs(1,1);
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/colazcy/p/11514983.html