CF903F Clear The Matrix

一、题目

点此看题

二、题目

由于能填的只有 1 × 1....4 × 4 1\times 1....4\times 4 4 4 种,可以考虑状压,相当于考虑 4 × 4 4\times 4 这样的方格如何去填。设 d p [ i ] [ s ] dp[i][s] 为考虑到第 i i 列,前 i 1 i-1 列都已经处理好了, i i + 3 i-i+3 的状态压缩(.是0*是1)为 s s 的最小花费。

转移就枚举操作的子矩阵(有一边在当前列上),可以预处理子矩阵的状态,把他们并起来得到新的状态。如果当前列已经被处理完,就可以转移到下一列的状态了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 1005;
const int inf = 0x3f3f3f3f;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,pos,w[5],f[M],a[5][5],b[5][5],dp[M][1<<16];
signed main()
{
    n=read();
    for(int i=1;i<=4;i++)
        w[i]=read();
    for(int i=1;i<=4;i++)
        for(int j=1;j<=n;j++)
        {
            char c;
            cin>>c;
            f[j]<<=1;
            if(c=='*') f[j]++;
        }
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4-i+1;j++)
        {
            for(int k=1;k<=4;k++)
                for(int l=1;l<=4;l++)
                    a[k][l]=1;
            for(int k=1;k<=j;k++)
                for(int l=0;l<j;l++)
                    a[k][i+l]=0;
            int now=0;
            for(int k=4;k>=1;k--)
                for(int l=1;l<=4;l++)
                    now=(now<<1)+a[k][l];
            b[i][j]=now;
        }
    memset(dp,0x3f,sizeof dp);
    for(int i=4;i>=1;i--)
    {
        pos<<=4;
        pos+=f[i];
    }
    dp[1][pos]=0;
    for(int i=1;i<=n;i++)
        for(int j=(1<<16)-1;j>=0;j--)
        {
            if(dp[i][j]==inf) continue;
            if(!(j&15))
            {
                int now=(f[i+4]<<12)|(j>>4);
                dp[i+1][now]=min(dp[i+1][now],dp[i][j]);
            }
            for(int k=1;k<=4;k++)
                for(int l=1;l<=4-k+1;l++)
                    dp[i][j&b[k][l]]=min(dp[i][j&b[k][l]],dp[i][j]+w[l]);
        }
    printf("%d\n",dp[n][0]);
}

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/107833780