概述
题目大意:
给你一个N*M的矩阵,其中有白色和黑色两种颜色,我们可以将其中的任意格子颜色变成另外一种颜色,问最少操作多少次(变换颜色),使得这个N*M的矩阵变成一个条形码,并且保证相同颜色挨在一起的列数不小于x不大于y、
思路:
1、首先预处理出每一列变成一种颜色需要多少花费,记做a【i】【2】,其中a【i】【0】表示将第i列都变成点的花费,a【i】【1】表示将第i列都变成#的花费。
2、那么考虑dp过程:
①设定dp【i】【j】【k(0/1)】表示现在进行到第i列上,当前列颜色为k(0/1),并且其前边的列与当前列颜色相同的连续列数为j的最小花费。
②那么不难推出其状态转移方程:
if(j==1)dp【i】【j】【k】=min(dp【i-1】【l】【k】,dp【i】【j】【k】+a【i】【k】)【x<=l<=y】
表示当前列的颜色要与上一列的颜色不同,那么其要满足上一列的颜色连续的列数在x到y之间,在这个区间内,维护最小值。
if(j!=1)dp【i】【j】【k】=dp【i-1】【j-1】【k】+a【i】【k】;
表示当前列的颜色要与上一列的颜色相同,那么直接从上一列的状态转移过来即可。
③时间复杂度O(m^2)
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char map[1005][1005];
int dp[1005][1005][2];
int a[1005][2];
int main()
{
int n,m,x,y;
while(~scanf("%d%d%d%d",&n,&m,&x,&y))
{
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
}
//a[j][0] 都弄成#
//a[j][1] 都弄成.
for(int j=0;j<m;j++)
{
int cnt=0;
for(int i=0;i<n;i++)
{
if(map[i][j]=='#')cnt++;
}
a[j][0]=cnt;
a[j][1]=n-cnt;
}
for(int i=0;i<m;i++)
{
if(i==0)
{
dp[i][1][0]=a[i][0];
dp[i][1][1]=a[i][1];
continue;
}
for(int j=1;j<=i+1&&j<=y;j++)
{
if(j==1)
{
for(int k=x;k<=y;k++)
{
dp[i][j][0]=min(dp[i][j][0],dp[i-1][k][1]+a[i][0]);
dp[i][j][1]=min(dp[i][j][1],dp[i-1][k][0]+a[i][1]);
}
}
else
{
dp[i][j][0]=dp[i-1][j-1][0]+a[i][0];
dp[i][j][1]=dp[i-1][j-1][1]+a[i][1];
}
}
}
int output=0x3f3f3f3f;
for(int i=x;i<=y;i++)
{
output=min(dp[m-1][i][0],output);
output=min(dp[m-1][i][1],output);
}
printf("%dn",output);
}
}
最后
以上就是冷傲电话为你收集整理的Codeforces 225C Barcode【dp】的全部内容,希望文章能够帮你解决Codeforces 225C Barcode【dp】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复