水叮当的舞步 深搜
背景 Background
水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。
为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~
描述 Description
地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。
输入格式 InputFormat
每个测试点包含多组数据。
每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。
接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。
N=0代表输入的结束。
输出格式 OutputFormat
对于每组数据,输出一个整数,表示最少步数。
样例输入 SampleInput
2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0
样例输出 SampleOutput
0
3
数据范围和注释 Hint
对于30%的数据,N<=5
对于50%的数据,N<=6
对于70%的数据,N<=7
对于100%的数据,N<=8,每个测试点不多于20组数据。
这题首先告诉我们,一定要审题,仔细审题,用心审题。
一开始看这道题,以为好难,要怎么怎么复杂地广搜。然后经过杨之典大触的指出后,我才知道其实每次只是动左上角那个联通块,于是问题就清晰了。
我们经过一定的思考,这题广搜其实没有深搜好用,于是我们就用深搜来解决这道题。
那么用深搜就一定要有一定的剪枝,所以我们来看看怎么剪枝。
首先第一个剪枝很明显,如果在ans步内已经搜到过目标,那么之后搜索的深度肯定在这个范围之内。
然后是第二个剪枝。假设我们现在图中有a中颜色,现在是b步,已经在ans步内搜到过答案,那么如果a+b>ans的话也没必要往下搜了,因为每次最多改变一种颜色。
第三个剪枝,假设我们左上角联通块周围的颜色是2,4,那么我们这时还要不要把左上角的联通块变成五个颜色往下搜呢?显然,我们只要把左上角的联通块变成2或4再往下搜,
变成其他颜色显然不是最优的。
第四个剪枝,是建设在第三个剪枝之上的,假设我们左上角的联通块周围的颜色是2,4,而且2有4个,4只有2个,那个我们先搜哪个呢?当然是先搜2,。
讲了这么多,感觉好麻烦,其实,真的很麻烦。
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() {int x=0,y=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')y=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*y; } il ll gl() {ll x=0,y=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')y=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*y; } int n; int ans; int map[10][10]; int pre[10][10]; bool v[10][10]; il bool check()//检查是否满足条件 {int now=map[1][1];for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(map[i][j]!=now)return 0;return 1; } il void hzr()//记录修改前的图 {for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)pre[i][j]=map[i][j]; } il void hzrr()//用来回溯 {for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)map[i][j]=pre[i][j]; } il int count()//用来做第二个剪枝的函数 {int sum=0;bool vis[45];for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(!vis[map[i][j]]){sum++;vis[map[i][j]]=1;}return sum; } struct col {int co,s; }c[10];//用来记录联通块周围的颜色种类和数量的结构体 bool cmp(col a,col b) {return a.s>b.s; } bool vis[10][10]; il void bfs()//bfs求联通块,并且记录左上角的联通块周围的颜色 {int head=0,tail=1;int t[100][2];//用来广搜的队列 for(int i=0;i<=5;i++)c[i].s=0,c[i].co=i;//初始化记录的结构体memset(vis,0,sizeof(vis));int dis[5]={0,1,0,-1,0};t[0][0]=1;t[0][1]=1;v[1][1]=1;vis[1][1]=1;while(head!=tail){for(int i=0;i<4;i++){int x=t[head][0]+dis[i],y=t[head][1]+dis[i+1];if(vis[x][y]||x>n||x<1||y>n||y<1)//如果在界外或者已是联通块里的 continue;if(map[x][y]!=map[1][1])//如果是周围的不同颜色的就记录 {c[map[x][y]].s++;continue;} vis[x][y]=1;t[tail][0]=x;t[tail++][1]=y;}head++;} } il void change(int x)//将联通块变成目标颜色 {for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(vis[i][j])map[i][j]=x; } viod dfs(int x) {if(x>ans)//第一个剪枝 return;if(check())//如果满足条件,那么就记录 {if(ans>x)ans=x;return;}if(x+count()>ans)//第二个剪枝 return;hzr();//为回溯做准备 bfs();//求出联通块,并且记录联通块周围的颜色种类和数量 sort(c,c+5,cmp);//按周围颜色出现的次数排序 for(int i=0;i<=5;i++){if(!c[i].s)break;change(c[i].co);//把联通块都变成目标颜色 dfs(x+1);//往下搜 hzrr();//回溯 } } int main() {while(1){n=gi();if(!n)break;ans=2e8;memset(map,0,sizeof(map));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)map[i][j]=gi(); dfs(0);printf("%d\n",ans);}return 0; }
转载于:https://www.cnblogs.com/gshdyjz/p/7360459.html
水叮当的舞步 深搜相关推荐
- [GMOJ]水叮当的舞步 From lydrainbowcat
水叮当的舞步 From lydrainbowcat 类型:IDA* (迭代加深启发式搜索) 方法一: 枚举每次选取了哪种颜色,然后找出左上角的格子所在的联通块,改变颜色. 为了避免来回改变.搜索深度过 ...
- 3422. 【NOIP2013模拟】水叮当的舞步
Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变. 为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 地毯上 ...
- 【IDA*】codevs 2495:水叮当的舞步
2495 水叮当的舞步 题目描述 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变. 为了讨好她的偶像虹猫,水叮当决定在地毯上 ...
- 【BZOJ】T3041 水叮当的舞步
题目链接: CODEVS 2495 水叮当的舞步 BZOJ 3041: 水叮当的舞步 这是道IDA*,迭代加深+估价剪枝: 首先考虑估价函数,一般情况下我们把易于计算的操作次数的下限作为A*的估价函数 ...
- codevs2495 水叮当的舞步(IDA*)
2495 水叮当的舞步 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题目描述 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物, ...
- 水管工游戏 (深搜)
水管工游戏 本题依然是采用搜索,深搜,广搜都可以,本代码采用深搜,此题在搜索时需要增加一些判断条件以及下一步要搜索的位置即可. 代码如下: #include<stdio.h> int a[ ...
- 【JZOJ】3422. 水叮当的舞步
Description Time Limits: 1000 ms Memory Limits: 262144 KB 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能 ...
- codevs 2495 水叮当的舞步
Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变.为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 地毯上的 ...
- Bzoj3041 水叮当的舞步
Time Limit: 10 Sec Memory Limit: 128 MB Submit: 132 Solved: 75 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼 ...
最新文章
- 《树莓派Python编程指南》—— 1.3 树莓派快速指南
- C#趣味程序---个位数为6,且能被3整出的五位数
- 计算机英语 TCP IP什意思,TCP/IP常见英文缩写释义
- php中td的属性设置,html table表格是什么?table标签中各种属性的使用方法
- 第三课 泛型+反射封装数据库访问层 2019-04-02
- SAP Kyma和SAP云平台上的Service instance
- 词汇挖掘与实体识别(未完)
- java and dsl_Groovy语法糖以及DSL
- 安卓学习随笔 -- 自定义标题栏
- python代码的层次结构_Python的object和type理解及主要对象层次结构
- 平面设计计算机基本配置,平面设计电脑配置要求
- 矩阵键盘mega16 c语言程序,51单片机对矩阵键盘实现16个按键操作的电路设计
- Kindle倒下,iReader接力
- [转]互联网系统架构的演进
- Swift如何实现与JSON互转
- 语音增强——DNN(深度神经网络)频谱映射
- mysql show processlist整理
- 学历学籍系统-Web服务开发实验(REST API)
- LAMP - 学习/实践
- WSL(Ubuntu20.04)与其图形界面安装配置