zoukankan      html  css  js  c++  java
  • P2258 子矩阵 (搜索,动态规划)

    题目链接


    Solution

    搜索+DP.
    刚好把搜索卡死的数据范围...
    然后应该可以很容易想到枚举行的情况,然后分列去DP.
    行的情况直接全排列即可,复杂度最高 (O(C_{16}^{8})).
    然后分列进行 DP, (f[i][j]) 代表以 (i) 为结尾,选了 (j) 个的答案.
    之后就是个简单的线性 DP ,对一些绝对值差进行预处理,复杂度 (O(n^3)) .
    总复杂度 (O(C_{16}^{8}*n^3)) ,可以过.

    Code

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,r,c;
    int w[20][20];
    int ans=0x3f3f3f3f;
    int a[20];
    
    void solve()
    {
        int lc[20]={0},rc[20][20]={0},f[20][20]={0};
        // 以 j 为结尾,长度为 k;
        for(int i=1;i<=m;i++)
        for(int j=1;j<=r;j++)
        {
        	for(int k=1;k<i;k++)
            rc[i][k]+=abs(w[a[j]][i]-w[a[j]][k]);
            if(j>1)
            lc[i]+=abs(w[a[j]][i]-w[a[j-1]][i]);
        }
        memset(f,127,sizeof(f));   
        f[1][1]=lc[1]; f[0][0]=0;
        for(int j=1;j<=m;j++)
        for(int k=1;k<=min(j,c);k++)
        for(int i=0;i<j;i++)
        f[j][k]=min(f[j][k],f[i][k-1]+rc[j][i]+lc[j]);
        for(int i=c;i<=m;i++)
        ans=min(f[i][c],ans);
        return;		
    }
    
    void dfs(int x)
    {
        if(x==r)
        {solve();return;}
        for(int i=a[x]+1;i<=n-(r-x)+1;i++)
        {a[x+1]=i;dfs(x+1);}
    }
    
    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",&w[i][j]);
        dfs(0);		
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    第二阶段站立会09
    第二阶段站立会08
    《大道至简》阅读笔记3
    《大道至简》阅读笔记2
    《大道至简》阅读笔记1
    站立会议9
    站立会议8
    站立会议6
    站立会议7
    站立会议5
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9672573.html
Copyright © 2011-2022 走看看