p3392暴力枚举

p3392
某国法律规定,只要一个由 N×M 个小方块组成的旗帜符合如下规则,就是合法的国旗。

从最上方若干行(至少一行)的格子全部是白色的;
接下来若干行(至少一行)的格子全部是蓝色的;
剩下的行(至少一行)全部是红色的;

现有一个棋盘状的布,分成了 N 行 M 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成该国国旗,方法是在一些格子上涂颜料,盖住之前的颜色。
小a很懒,希望涂最少的格子,使这块布成为一个合法的国旗。
输入格式
第一行是两个整数
N,M。
接下来 N行是一个矩阵,矩阵的每一个小方块是W(白),B(蓝),R(红)中的一个。

输入
4 5
WRWRW
BWRWB
WRWRW
RWBWR

输出格式
一个整数,表示至少需要涂多少块。

11

思路,枚举白和蓝的行数。

#include<stdio.h>
#include<string.h>
char a[100][100];
int W[100],B[100],R[100];
int n,m,ans=999999,sum;
int main()
{
    scanf("%d%d\n",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",&a[i]);
        for(int j=0; j<m; j++)
        {
            if(a[i][j]!='W')
                W[i]++;
            if(a[i][j]!='B')
                B[i]++;
            if(a[i][j]!='R')
                R[i]++;
        }
    }
    for(int i=2; i<n; i++)
        for(int j=i+1; j<=n; j++)
        {
            sum=0;
            for(int x=1; x<i; x++)
                sum+=W[x];
            for(int x=i; x<j; x++)
                sum+=B[x];
            for(int x=j; x<=n; x++)
                sum+=R[x];
            if(sum<ans)
                ans=sum;
        }
        printf("%d",ans);
        return 0;

}

前缀和优化

#include<stdio.h>
#include<string.h>
char a[100][100];
int W[100],B[100],R[100];
int fw,fb,fr;
int n,m,ans=999999,sum;
int main()
{
    scanf("%d%d\n",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",&a[i]);
        fw=0,fb=0,fr=0;
        for(int j=0; j<m; j++)
        {
            if(a[i][j]!='W')
              fw++;
            if(a[i][j]!='B')
                fb++;
            if(a[i][j]!='R')
                fr++;
        }
        W[i]=W[i-1]+fw;
        B[i]=B[i-1]+fb;
        R[i]=R[i-1]+fr;
    }
    for(int i=2; i<n; i++)
        for(int j=i+1; j<=n; j++)
        {
          sum=W[i-1]-W[0]+B[j-1]-B[i-1]+R[n]-R[j-1];
          if(sum<ans)
            ans=sum;
        }
        printf("%d",ans);
        return 0;

}

dp实现

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
char a[100][100];
int w[100][5],f[100][5];
int fw,fb,fr;
int n,m,ans=999999,sum;
int main()
{
    scanf("%d%d\n",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",&a[i]);
        for(int j=0; j<m; j++)
        {
            if(a[i][j]!='W')
              w[i][0]++;
            if(a[i][j]!='B')
            w[i][1]++;
            if(a[i][j]!='R')
            w[i][2]++;
        }

    }
    f[1][0]=w[1][0];
    f[1][1]=f[1][2]=9999999;
    for(int i=2;i<=n-1;i++){
        f[i][0]=f[i-1][0]+w[i][0];
        f[i][1]=min(f[i-1][0],f[i-1][1])+w[i][1];
        f[i][2]=min(f[i-1][1],f[i-1][2])+w[i][2];
    }
    for(int i=1;i<=2;i++)
        ans=min(ans,f[n-1][i]);
    printf("%d",ans+w[n][2]);
        return 0;

}

dfs实现

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,map[51][51],ans=99999999,color[51][4],b[51][51];
char ch;

int dfs(int x,int y,int t)
{
	if(x+y>=n)//超出边界
		return 0;
	if(b[x][y])//避免重复搜索,进行剪枝
		return 0;
	b[x][y]=1;
	dfs(x+1,y,t+color[x+1][1]);
	dfs(x,y+1,t+color[n-y][3]);
	if(x>0&&y>0&&x+y<n)
	{
		int k=0;
		for(int i=x+1;i<=n-y;i++)
			k+=color[i][2];
		ans=min(ans,t+k);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			do
				ch=getchar();
			while(int(ch)<65);
            //用getchar就要这样,否则行末回车会弄得你很头疼
            //还有,数据不能下载,鬼知道行末有几个空格,反正我被坑了
			if(ch=='W')//记得预处理
				map[i][j]=1,color[i][2]++,color[i][3]++;
			if(ch=='B')
				map[i][j]=2,color[i][1]++,color[i][3]++;
			if(ch=='R')
				map[i][j]=3,color[i][1]++,color[i][2]++;
		}
	}
	dfs(0,0,0);
	printf("%d",ans);
	return 0;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry_Sky_Dream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值