当前位置: 首页 > news >正文

hdu 4012 Paint on a Wall

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4012

下面分析转自大牛:http://www.cnblogs.com/ambition/archive/2011/09/08/Paint_on_a_Wall.html 

题目大意:给出一个2×n的矩阵(n<=8),每次给一个矩形染色,之后的染色覆盖以前的颜色,问到达目标状态需要多少次

看到题目数据量想到了要用搜索去做,想了很久才想出搜索方法,搜索题中的极品啊~~

因为每一次涂色肯定会有至少一块颜色是最终显示的颜色,所以用状态记录每一块是否是最终显示的颜色,因为只有2×8块,用二进制表示,搜索的顺序是每一块被染色顺序,在对某一块染色时把这个块最大能扩展到矩形全部染色,并将其中颜色和那一块相同的全部标记为最终显示的颜色

扩展就是向前和向后分别去判断,如果要扩展的块已经是最终显示颜色了,那么就不能扩展下去了,这样找到染色当前块的最大矩形,每个块可以扩展成单行和双行两种矩形

下面的代码我自己添加了一些解释,不难看懂:

#include<iostream>
#include<queue>
using namespace std;
struct node
{
	int v,cnt;
	//v标记当前状态,即16点是否已经全部达到最终状态
	//cnt表示当前状态已用的操作数
};
queue<node> Q;
char maze[20];//原矩阵
bool vis[1<<16];
int n;
int bfs()
{
	node q;
	q.v=q.cnt=0;
	Q.push(q);
	memset(vis,false,sizeof(vis));
	vis[0]=true;
	while(!Q.empty())
	{
		node tmp;
		q=Q.front();
		int u=q.v;
		Q.pop();
		for(int i=0;i<(n<<1);i++)
		{
			int v=u;
			if(v&(1<<i)) //若当前节点已经达到最终状态,continue
				continue;
			for(int j=i;j<(i/n+1)*n;j++)//循环控制好精湛啊,当时使用于i处在第一行和第二行的情况,从当前点向右遍历,看是否下一点是否相同
			{
				if(v&(1<<j)) break;
				if(maze[i]==maze[j]) v|=(1<<j);
			}
			for(int j=i-1;j>=(i/n)*n;j--)//从当前点向左遍历
			{
				if(v&(1<<j)) break;
				if(maze[i]==maze[j]) v|=(1<<j);
			}
			if(!vis[v])
			{
				vis[v]=true;	
				if(v==(1<<(n<<1))-1)//当前状态,所有点都达到最终状态
				return q.cnt+1;
				tmp.v=v;
				tmp.cnt=q.cnt+1;
				Q.push(tmp);
			}
			if(i/n)//下面是对每次画一个二行的矩阵的情况进行的讨论,所以当i大于n是continue
				continue;
			v=u;
			if(v&(1<<(i+n))) //若当前点的下方已经是最终状态,则无需画一个二行的矩阵,continue
				continue;
			for(int j=i;j<n;j++)//向右遍历
			{
				if((v&(1<<j))|(v&(1<<(j+n)))) //当前点或当前点的下面 的点已经到达最终状态
					break;
				if(maze[i]==maze[j]) v|=(1<<j);
				if(maze[i]==maze[j+n]) v|=(1<<(j+n));
			}
			for(int j=i-1;j>=0;j--)//向左遍历
			{
				if((v&(1<<j))|(v&(1<<(j+n))))break;
				if(maze[i]==maze[j]) v|=(1<<j);
				if(maze[i]==maze[j+n]) v|=(1<<(j+n));
			}
			if(!vis[v])
			{
				vis[v]=true;
				if(v==(1<<(n<<1))-1)
					return q.cnt+1;
				tmp.v=v;
				tmp.cnt=q.cnt+1;
				Q.push(tmp);
			}
		}
	}
}
int main()
{
	int cas,T=0;
	scanf("%d",&cas);
	while(cas--)
	{
		scanf("%d",&n);
		scanf("%s",maze);
		scanf("%s",maze+n);
		while(!Q.empty())
			Q.pop();
		printf("Case #%d: %d\n",++T,bfs());
	}
	return 0;
}

转载于:https://www.cnblogs.com/nanke/archive/2011/09/20/2182793.html

相关文章:

  • Android开发者指南(11) —— Optimizing Apps for Android 3.0
  • C#获取当前路径的7种方法
  • android116 轮播 viewPager实现
  • 参加虚拟化达人训练营的体会
  • 转载: 关于ruby中 %Q, %q, %W, %w, %x, %r, %s 的用法
  • django专题—安装、创建项目、添加应用
  • 自定义的asp.net翻页控件
  • python 数学运算符
  • 标题一定要长~~~~长~~~~~~~~~~~~~~长~~~~~~~~
  • python 中set模块的用法
  • Turbo C 2.0集成开发环境的使用
  • Ajax on Rails 2. The Eras of Web Development
  • 创建按钮的两种方法
  • JavaScript对象知识点总结
  • 在Python常用模块I如何打开相关文件的方法
  • ES6指北【2】—— 箭头函数
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • Debian下无root权限使用Python访问Oracle
  • leetcode讲解--894. All Possible Full Binary Trees
  • PHP那些事儿
  • React-Native - 收藏集 - 掘金
  • React系列之 Redux 架构模式
  • SegmentFault 2015 Top Rank
  • vue中实现单选
  • 闭包--闭包作用之保存(一)
  • 构建二叉树进行数值数组的去重及优化
  • 规范化安全开发 KOA 手脚架
  • 开发基于以太坊智能合约的DApp
  • 老板让我十分钟上手nx-admin
  • 悄悄地说一个bug
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 首页查询功能的一次实现过程
  • 数据科学 第 3 章 11 字符串处理
  • 微信小程序:实现悬浮返回和分享按钮
  • 异步
  • MPAndroidChart 教程:Y轴 YAxis
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • #etcd#安装时出错
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • $jQuery 重写Alert样式方法
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (八)Spring源码解析:Spring MVC
  • (汇总)os模块以及shutil模块对文件的操作
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (七)c52学习之旅-中断
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Framework .NET Core与 .NET 的区别
  • .Net MVC4 上传大文件,并保存表单
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net打印*三角形