【NOIP2013模拟】水叮当的舞步
2016-05-30 19:25
288 查看
Description
给出一个N*N的网格,每个格子有它的颜色0~5。每一次你可以选择一个颜色,然后把左上角的格子所在的联通块里的所有格子变成选择的那种颜色。这里的联通是指两个格子有公共边,并且颜色相同。
现在想问,最少需要多少次操作,才会使所有格子的颜色相同。
N<=8,数据组数<=20
Solution
玄学暴力题,各种无脑优化。考虑到答案不会特别大,可以使用迭代加深。
设一个估价函数(高大上),表示最少还需要的步数,如果当前深度+估价函数>限制就退出。
复杂度玄学,O(跑得过),对于这类题,Czy大神有话要说
Code
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define N 9 using namespace std; int v ,rev ,a ,id,n; int g[4][2]={0,1,0,-1,1,0,-1,0}; void fill(int x,int y,int c) { v[x][y]=1; fo(i,0,3) { int xx=x+g[i][0],yy=y+g[i][1]; if (xx>n||xx<1||yy>n||yy<1||v[xx][yy]==1) continue; v[xx][yy]=2; if (a[xx][yy]==c) fill(xx,yy,c); } } int pd() { int cnt=0;bool bz[6];memset(bz,0,sizeof(bz)); fo(i,1,n) fo(j,1,n) if (v[i][j]!=1&&!bz[a[i][j]]) { bz[a[i][j]]=1;cnt++; } return cnt; } bool can(int c) { bool bz=0; fo(i,1,n) fo(j,1,n) if (v[i][j]==2&&a[i][j]==c) { fill(i,j,c);bz=1; } return bz; } bool dfs(int x) { int p=pd(); if (x+p>id) return 0; if (!p) return 1; int rev ; memcpy(rev,v,sizeof(rev)); fo(i,0,5) { if (can(i)&&dfs(x+1)) return 1; memcpy(v,rev,sizeof(v)); } return 0; } int main() { for(scanf("%d",&n);n;scanf("%d",&n)) { fo(i,1,n) fo(j,1,n) scanf("%d",&a[i][j]); memset(v,0,sizeof(v)); fill(1,1,a[1][1]); for(id=0;id<=n*n;id++) if (dfs(0)) break; printf("%d\n",id); } }
相关文章推荐
- 集群、负载均衡及分布式系统架构
- 怎样使用U盘启动盘安装乌班图系统
- esnext:最后一个参数后面也允许加逗号了
- Maven 入门教程(二)
- 根据开始时间结束时间,开始的经纬度结束的经纬度,按照一定的时间频率生成坐标点。
- 第十、十一周项目1:阅读程序,并写出运行结果(3)
- LeetCode 55: Jump Game
- 设计模式之单例模式
- pvs环境中批处理安装PDF打印机
- android那些坑
- 数组类运算的实现
- 验证手机号或邮箱号是否合法
- du -sm * | sort -nr
- 重构Pomelo游戏框架的Unity客户端
- Android中ListView使用总结
- 一些 iOS问题解决
- java Socket编程
- 3.1 线性基函数模型
- Android文件/文件夹选择器(支持多选操作),已封装为lib库,直接添加依赖即可。
- ArrayList用法