noi1816 画家问题(技巧搜索Dfs)

本文介绍了一个被称为“画家问题”的算法挑战,通过枚举所有可能的第一行涂色方案,并使用递归函数来逐步确定后续行的涂色方式,最终找出使最后一行完全变为黄色所需的最小涂色次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
Problem 画家问题
假设一个ans数组存的是对每一个点的操作 0表示不图 1表示图
那么 对于原图 g 操作第三行时对第一行没有影响 同样往下类似的
所以 假设我们知道了ans的第一行就是最后答案的第一行 那么对于ans的第二行 就必须是的第一行全变成黄色
以此类推 最后检验第n行 是不是全部黄色就好了
所以只需要枚举第一行的所有情况 共2的n次方种情况 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define inff 0x7fffffff
using namespace std;
int n,ans[20][20],g[20][20],tmp[20][20],anss,minn=inff,tot;
char s;
void Printf()//计数 染了几个 
{
    anss=0;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        if(ans[i][j]==1)anss++;
    minn=min(minn,anss);
}
void Pai()//根据ans的第一行 逐行染色 
{
    int i,j,f=0;
    memset(tmp,0,sizeof(tmp));
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        tmp[i][j]=g[i][j];
    for(i=1;i<=n;i++)
      {
          if(ans[1][i]==1)
            {
              tmp[1][i]=!tmp[1][i];
              tmp[1][i+1]=!tmp[1][i+1];
              tmp[1][i-1]=!tmp[1][i-1];
              tmp[2][i]=!tmp[2][i];
          }
      }
    for(i=2;i<=n;i++)
      for(j=1;j<=n;j++)
        if(tmp[i-1][j]==1)
          {
            tmp[i-1][j]=0;
              ans[i][j]=1;
              tmp[i][j]=!tmp[i][j];
              tmp[i][j+1]=!tmp[i][j+1];
              tmp[i][j-1]=!tmp[i][j-1];
              tmp[i+1][j]=!tmp[i+1][j];
          }
    for(i=1;i<=n;i++)//最后检验最后一行是不是恰好全为黄色 
      if(tmp[n][i]==1)f=1;
    if(f==0)Printf();
}
void Dfs(int t)//枚举ans的第一行的所有情况 
{
    if(t>n)
      {
          for(int i=2;i<=n;i++)
            for(int j=1;j<=n;j++)
              ans[i][j]=0;
          Pai();
        return;
      }
    ans[1][t]=1;Dfs(t+1);
    ans[1][t]=0;Dfs(t+1);
}
int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        {
          cin>>s;
          if(s=='w')g[i][j]=1;
          else g[i][j]=0;
        }
    Dfs(1);
    if(minn<0x7fffffff)cout<<minn;
    else cout<<"inf";
}

 

转载于:https://www.cnblogs.com/yanlifneg/p/5405658.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值