zoukankan      html  css  js  c++  java
  • [codeforces]903F Clear The Matrix

    原题链接 :903F Clear The Matrix

    分析

    题目大意

    给定一个(4 imes n) 的矩阵,上面有'.'和'*'现在你可以用(1 imes 1),(2 imes 2),(3 imes 3),(4 imes 4)这四种'.'矩阵覆盖这个矩阵,要求覆盖后的矩阵只剩'.'。
    每一次覆盖有价值,四种大小的矩阵价值不同。
    求最小的总价值。

    其实状压dp是挺明显的,本来想打一发搜索,但是状态设计有点麻烦。
    考虑到矩阵宽度只有4,可以很明显来一发状压dp。
    状压最重要的是设计状态。
    dp[i][s]表示前i行已经全部被覆盖了,现在的状态为s。
    这样子很明显可以得到,当第一行全为'.'的时候,我们可以递推到第i+1行。
    然后我们预处理出用于覆盖矩形的状态。
    mk[i][k]表示矩形左上角放在第一行的第i个位置,矩形的大小为k,他的覆盖状态。
    然后递推就是(dp[i][s&mk[i][k]]=min{dp[i][s]+w[k]})
    这样子我们跑一遍dp就可以推出最终状态。
    时间复杂度O(能过)。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define ll long long
    using namespace std;
    int read(){
        char c;int num,f=1;
        while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
        while(c=getchar(), isdigit(c))num=num*10+c-'0';
        return f*num;
    }
    int n,a[10],f[1009],ans;
    int mk[10][10],m[10][10];
    int dp[1009][(1<<16)+4],qwq=0;
    char c;
    void init(){
        n=read();
        for(int i=1;i<=4;i++)a[i]=read();
        for(int i=0;i<4;i++){
            for(int j=0;j<n;j++){
                cin>>c;
                f[j]<<=1;
                f[j]+=(c=='*');
            }
        }
        for(int i=0;i<4;i++){
            for(int j=1;j<=4-i;j++){
                for(int k=0;k<4;k++)
                    for(int p=0;p<4;p++)
                        m[k][p]=1;
                for(int k=0;k<j;k++)
                    for(int p=0;p<j;p++)
                        m[k][i+p]=0;
                ans=0;
                for(int k=3;k>=0;k--){
                    for(int p=0;p<4;p++){
                        ans=(ans<<1)+m[k][p];
                    }
                }
                mk[i][j]=ans;
            }
        }
    }
    int main()
    {
        memset(dp,0x3f,sizeof(dp));
        init();
        //cout<<mk[0][3]<<endl;
        for(int i=3;i>=0;i--)
            qwq*=16,qwq+=f[i];
        dp[0][qwq]=0;
        for(int i=0;i<=n;i++){
            for(int s=(1<<16)-1;s>=0;s--){
                if(dp[i][s]>=0x3f3f3f3f-10)continue;
                if(!(s&15)){
                    int ss=(f[i+4]<<12)|(s>>4);
                    dp[i+1][ss]=min(dp[i+1][ss],dp[i][s]);
                }
                for(int k=0;k<4;k++)
                    for(int p=1;p<=4-k;p++)
                        dp[i][s&mk[k][p]]=min(dp[i][s&mk[k][p]],dp[i][s]+a[p]);
            }
        }
        printf("%d
    ",dp[n][0]);
        return 0;
    }
    /* mk[i][j]表示在第一行第i个位置摆一个大小为j的方块,它覆盖的状态*/	
    
  • 相关阅读:
    关于python的open函数encoding的入参
    控制台输出的log加颜色
    logging把log写到控制台
    合并两个list里的字典
    关于字典数组和元组合并
    python字典做入参调用时要写成**K这种形式
    python在循环中将含变量的字典加到列表中(问题:如果写法不当,会导致最后赋值的变量覆盖列表中前面赋值的变量)
    给定列表,按照列表内容获取excel指定列名下的内容
    selenum报错element is not attached to the page document
    python selenium获取input输入框中的值
  • 原文地址:https://www.cnblogs.com/onglublog/p/9874654.html
Copyright © 2011-2022 走看看