首页 > 其他分享 >耗时一天,逆天数字华容道代码

耗时一天,逆天数字华容道代码

时间:2024-08-22 15:26:14浏览次数:3  
标签:int 华容道 Move pos 耗时 zx swap 逆天 zy

\(O(n^3)\) 处理 \(n\times n\) 数字华容道还原(可能无解)。
具体实现看代码:

solve.cpp

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second

const int N = 201;
int n, l, r, L, R;
bool type;
vector<vector<int>> a, res;
vector<pair<int, int>> ans;
int fx[4] = {1, 0, -1, 0};
int fy[4] = {0, 1, 0, -1};
pair<int, int> pos[N * N];
//           U  L  D  R
inline void putans(int c) {
	if (c >= 4) c -= 4;
	int x = pos[0].fi + fx[c];
	int y = pos[0].se + fy[c];
	ans.emplace_back(x, y);
}

void Move(int val, int tx, int ty) {
	auto &[x, y] = pos[val];
	if (x == tx && y == ty) 
		return ;
	if (val == 0) { // 移动的是 0 那么固定移动直线
		while (x < tx) {
			int v = a[x + 1][y];
			putans(0 + type);
			swap(a[x + 1][y], a[x][y]);
			swap(pos[v], pos[0]);
		}
		while (x > tx) {
			int v = a[x - 1][y];
			putans(2 + type);
			swap(a[x - 1][y], a[x][y]);
			swap(pos[v], pos[0]);
		}
		while (y < ty) {
			int v = a[x][y + 1];
			putans(1 + type);
			swap(a[x][y + 1], a[x][y]);
			swap(pos[v], pos[0]);
		}
		while (y > ty) {
			int v = a[x][y - 1];
			putans(3 + type);
			swap(a[x][y - 1], a[x][y]);
			swap(pos[v], pos[0]);
		}
	} else {
		auto &[zx, zy] = pos[0];
		if (tx != l && zx == l) { // 特判第二行的点
			if (zy == y && zx + 1 == x) {
				if (y < R - 1) Move(0, zx, y + 1);
				else Move(0, zx, y - 1);
			}
			Move(0, zx + 1, zy);
		}
		while (y < ty) {
			if (zx == l) Move(0, zx + 1, zy);
			if (zx == x && zy < y) {
				if (zx == r - 1) Move(0, zx - 1, zy);
				else Move(0, zx + 1, zy);
			}
			Move(0, zx, y + 1);
			Move(0, x, y + 1);
			Move(0, x, y);
		}
		while (y > ty) {
			if (zx == x && zy > y) {
				if (zx == r - 1) Move(0, zx - 1, zy);
				else Move(0, zx + 1, zy);
			}
			Move(0, zx, y - 1);
			Move(0, x, y - 1);
			Move(0, x, y);
		}
		while (x > tx) {
			if (zy == y && zx < x) {
				Move(0, x - 1, y);
			} else {
				if (zy <= y && x != r - 1) {
					Move(0, x + 1, zy);
					Move(0, x + 1, y + 1);
				} 
				Move(0, x - 1, zy);
				Move(0, x - 1, y);
			}
			Move(0, x, y);
		}
	}
}

void solve() {
	if (r - l <= 3 && R - L <= 3) {
		static vector<vector<int>> tmp(3, vector<int>(3));
		vector<int> stk, st;
		for (int i = l; i < r; i++) {
			for (int j = L; j < R; j++) {
				tmp[i - l][j - L] = a[i][j];
				st.push_back(a[i][j]);
			}
		}
		int x = pos[0].fi - l, y = pos[0].se - L;
		map<int, int> pre;
		sort(st.begin(), st.end());

		auto key = [&](const vector<vector<int>> ve) {
			int res = 0;
			for (auto vv : ve) 
				for (auto x : vv) 
					res = res * 10 + lower_bound(st.begin(), st.end(), x) - st.begin();
			return res;
		};
		queue<pair<vector<vector<int>>, pair<int, int>>> q;
		q.push({tmp, {x, y}});
		pre[key(tmp)] = -1;
		while (!q.empty()) {
			auto [u, tt] = q.front();
			auto [x, y] = tt;
			q.pop();
			bool ok = true;
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 3; j++) {
					if (u[i][j] != res[i + l][j + L]) {
						ok = false;
						break;
					}
				}
			}
			if (ok) {
				while (pre[key(u)] != -1) {
					int i = pre[key(u)];
					stk.push_back(i);
					int xx = x - fx[i];
					int yy = y - fy[i];
					swap(u[xx][yy], u[x][y]);
					x = xx, y = yy;
				}
				reverse(stk.begin(), stk.end());
				for (auto x : stk) {
					putans(x);
				}
				puts("Find the solution:");
				printf("The solution steps is: %d\n", (int)ans.size());
				int idx = 0;
				for (auto [x, y] : ans) {
					++idx;
					printf("The %d : (%d %d)\n", idx, x, y);
				}
				return ;
			}
			for (int i = 0; i < 4; i++) {
				int xx = x + fx[i];
				int yy = y + fy[i];
				if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) {
					swap(u[x][y], u[xx][yy]);
					swap(x, xx);
					swap(y, yy);
					int kk = key(u);
					if (!pre.count(kk)) {
						pre[kk] = i;
						q.push({u, {x, y}});
					}
					swap(x, xx);
					swap(y, yy);
					swap(u[x][y], u[xx][yy]);
				}
			}
		}
		puts("No solution!");
		return ;
	}
	if (r - l <= 3) {
		auto _a = a, _res = res;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				a[j][n - i - 1] = _a[i][j];
				res[j][n - i - 1] = _res[i][j];
			}
		}
		for (int v = 0; v < n * n; v++) {
			swap(pos[v].fi, pos[v].se);
			pos[v].se = n - pos[v].se - 1;
		}
		swap(l, L);
		swap(r, R);
		swap(L, R);
		L = n - L, R = n - R;
		type = !type;
		return solve();
	}
	bool ok = true;
	for (int i = L; i < R; i++) {
		ok &= a[l][i] == res[l][i];
	}
	if (!ok) {
		Move(res[l][L + 1], l, L);
		if (pos[res[l][L]].fi == l) {
			Move(0, l + 1, pos[0].se);
			Move(0, l + 1, pos[res[l][L]].se);
			Move(0, l, pos[0].se);
			if (pos[0].se + 1 < R)
				Move(0, l, pos[0].se + 1);
			else
				Move(0, l, pos[0].se - 1);
			Move(0, l + 1, pos[0].se);
		}
		Move(res[l][L], l + 1, L);
		for (int j = L + 1; j < R - 1; j++) {
			Move(res[l][j + 1], l, j);
		}
		Move(0, pos[0].fi, R - 1);
		Move(0, l, R - 1);
		Move(0, l, L);
		Move(0, l + 1, L);
	}
	l++;
	solve();
}

int main() {
	scanf("%d", &n);
	a.resize(n, vector<int>(n));
	res.resize(n, vector<int>(n));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			scanf("%d", &a[i][j]);
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (i < n - 1 || j < n - 1) res[i][j] = i * n + j + 1;
			pos[a[i][j]].fi = i;
			pos[a[i][j]].se = j;
		}
	}
	l = L = 0, r = R = n;
	solve();
	return 0;
}

标签:int,华容道,Move,pos,耗时,zx,swap,逆天,zy
From: https://www.cnblogs.com/weirdoX/p/18373972

相关文章

  • 一次Kubernetes Pod内存异常导致的测试环境耗时异常问题排查过程
    概述在使用公司内部后台系统测试环境时发现一个请求加载慢的问题,简简单单的列表,查询MongoDB数据库,测试环境不过几百上千条数据而已,请求耗时居然高达5~6秒:作为对比,生产环境的请求响应截图如下:经过持续跟进,该后台系统所有列表页面测试环境普遍比生产环境慢,不管是MongoDB还是MyS......
  • 计算函数耗时
     C++计算函数耗时的类。在需要计算耗时的类里面,定义这个类的对象即可。#ifndef__ELAPSE_MILLSEC_H__#define__ELAPSE_MILLSEC_H__//#include<iostream>#include<chrono>#include<iomanip>//用于设置输出流的格式usingnamespacestd;//计算耗时class......
  • 逆天20w赞!吴恩达+Open AI打造《大模型通关指南》
    本书介绍LLM(LargeLanguageModels)正在逐步改变人们的生活,对于开发者来说,如何利用LLM提供的API快速、便捷地开发具备更强大能力、集成LLM的应用程序,以实现更新颖、更实用的功能,是一项急需学习的重要技能。吴恩达老师与OpenAI合作推出的大模型系列教程,从大模型时代开发者的......
  • AI客服中心6大逆天优势!留住客户都靠它!
    在数字化时代的大潮中,企业与客户之间的互动方式正经历着前所未有的变革。随着人工智能技术的飞速发展,AI客服中心作为连接企业与客户的桥梁,正逐步成为企业提升服务品质、增强客户体验的关键力量。它不仅仅是一个技术创新的产物,更是企业转型升级、实现可持续发展的重要推手。......
  • 定义一个C++的类,析构的时候输出当前函数执行耗时
    背景介绍:有时候我们需要知道一个函数的执行耗时。按照传统方法,至少要定义一个start,end,然后计算差值,输出差值,4个步骤。这里,我们定义一个  ElapseMillsec类,然后在类的生命周期结束的时候,在析构函数里面计算出差值。此时  ElapseMillsec类的生命周期,就是函数执行耗......
  • Cool Request重大更新:可以统计任意方法耗时【送源码】
    什么是CoolRequestCoolRequest是一个IDEA中的接口调试插件,除了可以发起基本的HTTP请求之外,还提供了强大的反射调用能力,可以绕过拦截器,这点广受网友的好评,当然伴随着还有Spring中对@Scheduled注解的调用,以及xxl-job的支持,这是不是很酷(Cool)?什么是Trace我怀着一颗激动的心......
  • 我们的前端开发逆天了!1 小时搞定了新网站,还跟我说 “不要钱”
    大家好,我是程序员鱼皮。前段时间我们上线了一个新软件剪切助手,并且针对该项目做了一个官网:很多同学表示官网很好看,还好奇是怎么做的,其实这个网站的背后还有个有趣的小故事。。。鱼皮:我们要做个官网,能下载应用就行,一周时间怎么样?我们的前端开发-多喝热水同学:一周?太小瞧我了......
  • 一个正式项目使用GraalVM进行native compile的启动耗时比较
    环境windows、graalvm(内置有JDK,可以不用再单独下载jdk了)项目pom.xml...<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version>......
  • C# 开发技巧 轻松监控方法执行耗时
    前言MethodTimer.Fody是一个功能强大的库,可以用于测量.NET应用程序中的方法的执行时间。允许你在不修改代码的情况下,自动地测量和记录方法的执行时间。这个工具是基于.NET的weaving技术,通过修改IL(IntermediateLanguage,中间语言)代码来插入计时逻辑,从而在方法调用前后记录时......
  • 一种网卡通讯慢或ping耗时较久的解决办法
    一、现象与问题        测试多台设备时候,在一个局域网的情况下,分别ping两台设备,发现ping指令耗时差距非常大,通过对比发现是其中较慢的一台设备网卡开启了PowerManagement功能,即PowerManagement:on.资料显示PowerManagement:on有以下功能 二、怀疑与疑问 ......