NOIP2011提高組.瑪雅游戲

目錄

題目

185. 瑪雅游戲
在這里插入圖片描述

算法標簽: 模擬, 搜索, d f s dfs dfs, 剪枝優化

思路

可行性剪枝

  • 如果某個顏色的格子數量少于 3 3 3一定無解
  • 因為要求字典序最小, 因此當一個格子左邊有格子, 不能向左移動, 應該向右移動, 具體來說當前位置向左移動 ( x , y , ? 1 ) (x, y, -1) (x,y,?1), 但是左邊格子向右移動 ( x ? 1 , y , 1 ) (x - 1, y, 1) (x?1,y,1), 字典序是更小的
    因為每個格子整體上向右移動

時間復雜度 3 5 5 35 ^ 5 355大概 5 × 1 0 7 5 \times 10 ^ 7 5×107

*詳細注釋版代碼

#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int R = 7, C = 5, S = 5;
const int TYPE = 11;int n; // 需要通關的步數
int g[C][R]; // 游戲棋盤,5列7行(x:0-4, y:0-6)
int bg[S][C][R]; // 備份棋盤狀態,用于回溯,bg[step][x][y]表示第step步時的棋盤狀態
int cnt[TYPE]; // 統計每種顏色方塊的數量,cnt[0]是所有方塊總數,cnt[1-10]是各顏色方塊數
int bcnt[S][TYPE]; // 備份方塊數量統計,用于回溯
bool st[C][R]; // 標記哪些方塊需要被消除struct Path {int x, y, d; // 記錄移動路徑:x,y是坐標,d是方向(1右,-1左)
} path[5]; // 存儲每一步的移動// 移動方塊并處理消除和掉落
void move(int a, int b, int c) {// 交換兩個方塊swap(g[a][b], g[c][b]);while (true) {bool flag = true; // 標記是否還有可以消除的方塊// 處理懸空方塊,讓方塊下落for (int x = 0; x < 5; x++) {int z = 0;// 壓縮非空方塊到列底部for (int y = 0; y < 7; y++)if (g[x][y])g[x][z++] = g[x][y];// 上方補0while (z < 7) g[x][z++] = 0;}// 檢查可以消除的方塊memset(st, 0, sizeof st);for (int x = 0; x < 5; x++)for (int y = 0; y < 7; y++)if (g[x][y]) {// 檢查水平方向是否有3個或以上連續相同方塊int l = x, r = x;while (l - 1 >= 0 && g[l - 1][y] == g[x][y]) l--;while (r + 1 < 5 && g[r + 1][y] == g[x][y]) r++;if (r - l + 1 >= 3) {st[x][y] = true;flag = false;}else {// 檢查垂直方向是否有3個或以上連續相同方塊l = r = y;while (l - 1 >= 0 && g[x][l - 1] == g[x][y]) l--;while (r + 1 < 7 && g[x][r + 1] == g[x][y]) r++;if (r - l + 1 >= 3) {st[x][y] = true;flag = false;}}}// 如果沒有可以消除的方塊,退出循環if (flag) break;// 消除標記的方塊for (int x = 0; x < 5; x++)for (int y = 0; y < 7; y++)if (st[x][y]) {cnt[0]--; // 總數減1cnt[g[x][y]]--; // 對應顏色方塊數減1g[x][y] = 0; // 清空該位置}}
}// 深度優先搜索解決瑪雅難題
bool dfs(int u) {// 如果達到目標步數且所有方塊都被消除,返回成功if (u == n) return !cnt[0];// 剪枝:如果有顏色只剩1或2個方塊,不可能消除完,提前返回for (int i = 1; i <= 10; i++)if (cnt[i] == 1 || cnt[i] == 2)return false;// 備份當前狀態memcpy(bg[u], g, sizeof g);memcpy(bcnt[u], cnt, sizeof cnt);// 枚舉所有可能的移動for (int x = 0; x < 5; x++)for (int y = 0; y < 7; y++)if (g[x][y]) {// 嘗試向右移動int nx = x + 1;if (nx < 5) {path[u] = {x, y, 1}; // 記錄路徑move(x, y, nx); // 執行移動if (dfs(u + 1)) return true; // 遞歸搜索// 回溯memcpy(g, bg[u], sizeof g);memcpy(cnt, bcnt[u], sizeof cnt);}// 嘗試向左移動nx = x - 1;if (nx >= 0 && !g[nx][y]) { // 左邊為空才能移動(否則會與向右移動重復)path[u] = {x, y, -1}; // 記錄路徑move(x, y, nx); // 執行移動if (dfs(u + 1)) return true; // 遞歸搜索// 回溯memcpy(g, bg[u], sizeof g);memcpy(cnt, bcnt[u], sizeof cnt);}}return false;
}int main() {scanf("%d", &n);// 讀取初始棋盤for (int x = 0; x < 5; x++) {int t, y = 0;while (scanf("%d", &t), t) {cnt[0]++; // 總數增加cnt[t]++; // 對應顏色方塊數增加g[x][y++] = t; // 放置方塊}}// 深度優先搜索if (dfs(0)) {// 輸出解決方案for (int i = 0; i < n; i++)printf("%d %d %d\n", path[i].x, path[i].y, path[i].d);}else {// 無解puts("-1");}return 0;
}

精簡注釋版代碼

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>using namespace std;const int R = 7, C = 5, S = 5;
const int TYPE = 11;int n;
int g[C][R], bg[S][C][R];
int cnt[TYPE], bcnt[S][TYPE];
bool vis[C][R];struct Path {int x, y, d;
} path[S];// 處理方塊移動和消除
void move(int a, int b, int na) {swap(g[a][b], g[na][b]);while (true) {bool flag = true;// 處理懸空方塊,讓它們下落for (int x = 0; x < C; ++x) {int z = 0;// 壓縮非空方塊到列底部for (int y = 0; y < R; ++y) {if (g[x][y]) {g[x][z++] = g[x][y];}}// 填充剩余位置為空while (z < R) {g[x][z++] = 0;}}memset(vis, false, sizeof vis);for (int x = 0; x < C; ++x) {for (int y = 0; y < R; ++y) {if (g[x][y]) {// 檢查橫向int l = x, r = x;while (l - 1 >= 0 && g[l - 1][y] == g[x][y]) l--;while (r + 1 < C && g[r + 1][y] == g[x][y]) r++;if (r - l + 1 >= 3) {vis[x][y] = true;flag = false;}// 檢查縱向else {int u = y, d = y;while (u - 1 >= 0 && g[x][u - 1] == g[x][y]) u--;while (d + 1 < R && g[x][d + 1] == g[x][y]) d++;if (d - u + 1 >= 3) {vis[x][y] = true;flag = false;}}}}}if (flag) break;// 消除標記的方塊for (int x = 0; x < C; ++x) {for (int y = 0; y < R; ++y) {if (vis[x][y]) {cnt[0]--;cnt[g[x][y]]--;g[x][y] = 0;}}}}
}bool dfs(int u) {if (u == n) return !cnt[0];for (int i = 1; i <= 10; ++i) {if (cnt[i] == 1 || cnt[i] == 2) return false;}// 備份當前狀態memcpy(bg[u], g, sizeof g);memcpy(bcnt[u], cnt, sizeof cnt);// 嘗試所有可能的移動for (int x = 0; x < C; ++x) {for (int y = 0; y < R; ++y) {if (g[x][y]) {// 向右移動if (x + 1 < C) {path[u] = {x, y, 1};move(x, y, x + 1);if (dfs(u + 1)) return true;memcpy(g, bg[u], sizeof g);memcpy(cnt, bcnt[u], sizeof cnt);}// 向左移動if (x - 1 >= 0 && !g[x - 1][y]) {path[u] = {x, y, -1};move(x, y, x - 1);if (dfs(u + 1)) return true;memcpy(g, bg[u], sizeof g);memcpy(cnt, bcnt[u], sizeof cnt);}}}}return false;
}int main() {ios_base::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n;for (int x = 0; x < C; ++x) {int t, y = 0;while (cin >> t, t) {cnt[0]++;cnt[t]++;g[x][y++] = t;}}if (dfs(0)) {for (int i = 0; i < n; ++i) {cout << path[i].x << " " << path[i].y << " " << path[i].d << "\n";}}else {cout << -1 << "\n";}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900797.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900797.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900797.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

go游戲后端開發29:實現游戲內聊天

接下來&#xff0c;我們再來開發一個功能&#xff0c;這個功能相對簡單&#xff0c;就是聊天。在游戲里&#xff0c;我們會收到一個聊天請求&#xff0c;我們只需要做一個聊天推送即可。具體來說&#xff0c;就是誰發的消息&#xff0c;就推送給所有人&#xff0c;包括消息內容…

基于大數據的美團外賣數據可視化分析系統

【大數據】基于大數據的美團外賣數據可視化分析系統 &#xff08;完整系統源碼開發筆記詳細部署教程&#xff09;? 目錄 一、項目簡介二、項目界面展示三、項目視頻展示 一、項目簡介 該系統通過對海量外賣數據的深度挖掘與分析&#xff0c;能夠為美團外賣平臺提供運營決策支…

[ctfshow web入門] web32

前置知識 協議相關博客&#xff1a;https://blog.csdn.net/m0_73353130/article/details/136212770 include&#xff1a;include "filename"這是最常用的方法&#xff0c;除此之外還可以 include url&#xff0c;被包含的文件會被當做代碼執行。 data://&#xff1a…

kotlin中const 和val的區別

在 Kotlin 中&#xff0c;const 和 val 都是用來聲明常量的&#xff0c;但它們的使用場景和功能有所不同&#xff1a; 1. val: val 用于聲明只讀變量&#xff0c;也就是不可修改的變量&#xff08;類似于 Java 中的 final 變量&#xff09;。它可以是任何類型&#xff0c;包括…

【STM32】綜合練習——智能風扇系統

目錄 0 前言 1 硬件準備 2 功能介紹 3 前置配置 3.1 時鐘配置 3.2 文件配置 4 功能實現 4.1 按鍵功能 4.2 屏幕功能 4.3 調速功能 4.4 倒計時功能 4.5 搖頭功能 4.6 測距待機功能 0 前言 由于時間關系&#xff0c;暫停詳細更新&#xff0c;本文章中&#xff0c;…

任務擴展-輸入商品原價,折扣并計算促銷后的價格

1.在HbuilderX軟件中創建項目&#xff0c;把項目的路徑放在xampp中的htdocs 2.創建php文件&#xff1a;price.php,price_from.php 3.在瀏覽器中&#xff0c;運行項目效果&#xff0c;通過xampp中admin進行運行瀏覽&#xff0c;在后添加文件名稱即可&#xff0c;注意&#xff…

3D Gaussian Splatting as MCMC 與gsplat中的應用實現

3D高斯潑濺(3D Gaussian splatting)自2023年提出以后,相關研究paper井噴式增長,盡管出現了許多改進版本,但依舊面臨著諸多挑戰,例如實現照片級真實感、應對高存儲需求,而 “懸浮的高斯核” 問題就是其中之一。浮動高斯核通常由輸入圖像中的曝光或顏色不一致引發,也可能…

【軟件測試】Postman中如何搭建Mock服務

在 Postman 中&#xff0c;Mock 服務是一項非常有用的功能&#xff0c;允許你在沒有實際后端服務器的情況下模擬 API 響應。通過創建 Mock 服務&#xff0c;你可以在開發階段或測試中模擬 API 的行為&#xff0c;幫助團隊成員進行前端開發、API 測試和集成測試等工作。 Mock 服…

Spring-MVC

Spring-MVC 1.SpringMVC簡介 - SpringMVC概述 SpringMVC是一個基于Spring開發的MVC輕量級框架&#xff0c;Spring3.0后發布的組件&#xff0c;SpringMVC和Spring可以無縫整合&#xff0c;使用DispatcherServlet作為前端控制器&#xff0c;且內部提供了處理器映射器、處理器適…

關于Spring MVC中@RequestParam注解的詳細說明,用于在前后端參數名稱不一致時實現參數映射。包含代碼示例和總結表格

以下是關于Spring MVC中RequestParam注解的詳細說明&#xff0c;用于在前后端參數名稱不一致時實現參數映射。包含代碼示例和總結表格&#xff1a; 1. 核心作用 RequestParam用于顯式綁定HTTP請求參數到方法參數&#xff0c;支持以下場景&#xff1a; 參數名不一致&#xff1…

MySQL主從復制技術詳解:原理、實現與最佳實踐

目錄 引言&#xff1a;MySQL主從復制的技術基礎 MySQL主從復制的實現機制 復制架構與線程模型 復制連接建立過程 數據變更與傳輸流程 MySQL不同復制方式的特點與適用場景 異步復制&#xff08;Asynchronous Replication&#xff09; 全同步復制&#xff08;Fully Synch…

ROS Master多設備連接

Bash Shell Shell是位于用戶與操作系統內核之間的橋梁&#xff0c;當用戶在終端敲入命令后&#xff0c;這些輸入首先會進入內核中的tty子系統&#xff0c;TTY子系統負責捕獲并處理終端的輸入輸出流&#xff0c;確保數據正確無誤的在終端和系統內核之中。Shell在此過程不僅僅是…

Trae + LangGPT 生成結構化 Prompt

Trae LangGPT 生成結構化 Prompt 0. 引言1. 安裝 Trae2. 克隆 LangGPT3. Trae 和 LangGPT 聯動4. 集成到 Dify 中 0. 引言 Github 上 LangGPT 這個項目&#xff0c;主要向我們介紹了寫結構化Prompt的一些方法和示例&#xff0c;我們怎么直接使用這個項目&#xff0c;輔助我們…

《安富萊嵌入式周報》第352期:手持開源終端,基于參數陣列的定向揚聲器,炫酷ASCII播放器,PCB電阻箱,支持1Ω到500KΩ,Pebble智能手表代碼重構

周報匯總地址&#xff1a;嵌入式周報 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬漢嵌入式論壇 - Powered by Discuz! 視頻版 https://www.bilibili.com/video/BV1DEf3YiEqE/ 《安富萊嵌入式周報》第352期&#xff1a;手持開源終端&#x…

python 淺拷貝copy與深拷貝deepcopy 理解

一 淺拷貝與深拷貝 1. 淺拷貝 淺拷貝只復制了對象本身&#xff08;即c中的引用&#xff09;。 2. 深拷貝 深拷貝創建一個新的對象&#xff0c;同時也會創建所有子對象的副本&#xff0c;因此新對象與原對象之間完全獨立。 二 代碼理解 1. 案例一 a 10 b a b 20 print…

day22 學習筆記

文章目錄 前言一、遍歷1.行遍歷2.列遍歷3.直接遍歷 二、排序三、去重四、分組 前言 通過今天的學習&#xff0c;我掌握了對Pandas的數據類型進行基本操作&#xff0c;包括遍歷&#xff0c;去重&#xff0c;排序&#xff0c;分組 一、遍歷 1.行遍歷 intertuples方法用于遍歷D…

SpringMVC的請求-文件上傳

文件上傳客戶端三要素 1. 表單項type“file” 2. 表單的提交方式是post 3. 表單的enctype屬性是多部分表單形式&#xff0c;及enctype“multipart/form-data” <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <he…

在Ubuntu系統如何讓MySQL服務器支持遠程連接

目錄 問題描述 解決方案 步驟一&#xff1a;檢查MySQL配置文件 ?編輯 步驟二&#xff1a;修改bind-address參數 ?編輯 步驟三&#xff1a;重啟MySQL服務 步驟四&#xff1a;驗證更改 步驟五&#xff1a;檢查防火墻設置 步驟六&#xff1a;測試遠程連接 注意事項 …

JSON工具-JSONUtil

對象轉JSON JSONUtil.toJsonStr可以將任意對象&#xff08;Bean、Map、集合等&#xff09;直接轉換為JSON字符串。 如果對象是有序的Map等對象&#xff0c;則轉換后的JSON字符串也是有序的。 //region 處理POST請求&#xff0c;將TreeMap轉換為JSON字符串返回/*** 處理POST請求…

死鎖 手撕死鎖檢測工具

目錄 引言 一.理論聯立 1.死鎖的概念和原因 2.死鎖檢測的基本思路 3.有向圖在死鎖檢測中的應用 二.代碼實現案例&#xff08;我們會介紹部分重要接口解釋&#xff09; 1.我們定義一個線性表來存線程ID和鎖ID 2.表中數據的查詢接口 3.表中數據的刪除接口 4.表中數據的添…