1. 程式人生 > >Hopping dots (獨立鑽石棋變種)攻略

Hopping dots (獨立鑽石棋變種)攻略

前言:這篇文章,我想完整的討論一個遊戲,叫Hopping dots,被翻譯為邏輯難題。

關鍵詞:獨立鑽石棋、深度優先搜尋、可能性分析、狀態壓縮、動態規劃的備忘錄方法

一,APK下載連結

我的版本:Hopping dots 1.1

二,遊戲介面、棋盤、棋子

(下圖為第一關)

(棋盤由13個點組成)


棋子:1個紅子和若干個綠子

三,規則

按照獨立鑽石棋的規則進行吃子,最後只剩下一個子,且為紅子,即為勝利。(無論紅子在何處)

這是我自己總結的規則,非常簡潔,初一看貌似不準確,仔細一想實際上和官方的定義是一樣的。

四,初步認識

1,棋子的數量

棋子最多有12個,最少有1個。

13個棋子肯定是死局面(無法勝利的局面),因為沒法進行操作。

12個棋子的局面中,存不存在活局面(能夠勝利的局面),這個暫且不知。

2,棋子數量變化

每次操作,棋子數量都是少1,所以,任何局面,最多隻能再進行11次操作

3,問題的簡化

問題的簡化版:只有綠子沒有紅子,只要最後只剩下一個子即為勝利(同樣不論位置)

這樣的版本就更接近獨立鑽石棋了,準確說來,除了棋盤和獨立鑽石棋不一樣之外,沒有任何差異。

對於玩家來說,原問題和問題的簡化版差異並不是很大,玩起來難度差不多。

而對於想做理論分析的筆者來說,原問題分析起來很繁瑣,掩蓋了很多規律。

如果只是想直接嘗試編寫深度優先搜尋的程式解決問題,其實是不需要簡化的,但是如果要嚴謹一些,先從理論上分析可能性大小,所以如此簡化正是第一步便要做的事情。

4,局面的數量(問題的簡化版)

有13個點是可能有子的,所以局面的數量為2^13=8192

其中還包括了大量的死局面,具體有多少活局面,我們並不關心。

5,編號


6,記錄所有的邊(不考慮方向)

不難數出,一共有16條邊

以2、6、8、12為中點的邊各有1條,如1-2-3

以4、5、9、10位中點的邊各有2條,如1-4-7,2-4-6

以7為中點的邊有4條,如2-7-12,4-7-10

之所以不考慮方向,是因為任何時候,一條邊最多對應一種可行操作,

以邊1-2-3為例,同一局面下,“從1跳到3”和“從3跳到1”不可能都是可行的操作。

注意到,每條邊的3個數都是等差陣列,所以一條邊只需要2個數字即可記錄下來,

這樣,便可以用2個長度為16的陣列來記錄下16條邊了。

int st[16] = { 1, 1, 3, 11, 1, 2, 2, 3, 6, 7, 8, 7, 4, 5, 6, 2 };
int en[16] = { 3, 11, 13, 13, 7, 6, 8, 7, 12, 11, 12, 13, 10, 9, 8, 12 };

五,深度優先搜尋的可能性分析(問題的簡化版)

因為最多隻能進行11次操作,所以深度優先搜尋的深度不深。現在需要計算的是,每一次操作有多少種選擇?

1,任一局面有多少種選擇

我們需要一個函式,輸入一個局面,輸出一個數值,告訴我們有多少種選擇。

如何輸入呢?使用狀態壓縮最為方便。

13個點,每個點對應一位,1表示有子,0表示沒有子,這樣,8192個局面便可以和8192個13位二進位制數一一對應了。

輸入之後,函式就可以直接計算出有多少種選擇了,時間為O(1)

有了這個函式,只要從0到8191列舉n,就能求出f(n)的最大值了,結果是10

程式碼:

#include <iostream>
using namespace std;

int st[16] = { 1, 1, 3, 11, 1, 2, 2, 3, 6, 7, 8, 7, 4, 5, 6, 2 };
int en[16] = { 3, 11, 13, 13, 7, 6, 8, 7, 12, 11, 12, 13, 10, 9, 8, 12 };

int f(int n)
{
	int r = 0, s, e, m;
	for (int i = 0; i < 16; i++)
	{
		s = st[i], e = en[i], m = (s + e) / 2;
		if ((n >> (13 - m)) & 1)r += ((n >> (13 - s)) & 1) ^ ((n >> (13 - e)) & 1);
	}
	return r;
}

int main()
{
	int maxx = 0;
	for (int n = 0; n < 8192; n++)if (maxx < f(n))maxx = f(n);
	cout << maxx;
	return 0;
}

2,深度優先搜尋的複雜度

前面分別算出,一個局面最多能再進行11次操作,每次操作最多10種選擇,那麼,用深度優先搜尋解決這個問題最多需要10^11次列舉計算。這是一個很大的數,普通的筆記本要算很久。

然而,我們不難發現,並非每次操作都有10種選擇,比如只剩2個子的時候最多隻有2種選擇。

那麼如果一個局面有k(1<k<13)個子,這個局面最多有多少種選擇?

只需利用上面的函式f即可。

程式碼:

#include <iostream>
using namespace std;

int st[16] = { 1, 1, 3, 11, 1, 2, 2, 3, 6, 7, 8, 7, 4, 5, 6, 2 };
int en[16] = { 3, 11, 13, 13, 7, 6, 8, 7, 12, 11, 12, 13, 10, 9, 8, 12 };
int num[14];//k個棋子的所有局面中最多有多少種選擇

void f(int n)
{
	int r = 0, s, e, m, k = 0;
	for (int i = 0; i < 16; i++)
	{
		s = st[i], e = en[i], m = (s + e) / 2;
		if ((n >> (13 - m)) & 1)r += ((n >> (13 - s)) & 1) ^ ((n >> (13 - e)) & 1);
	}
	while (n)
	{
		k += n & 1;
		n /= 2;
	}
	if (num[k] < r)num[k] = r;
}

int main()
{
	for (int i = 0; i < 14; i++)num[i] = 0;
	for (int n = 0; n < 8192; n++) f(n);
	for (int i = 2; i <= 12; i++)cout << num[i] << "  ";
	return 0;
}

執行結果:

2  4  7  7  9  10  9  9  8  6  4

2*4*7*7*9*10*9*9*8*6*4=548674560,所以任何一個局面,進行深度優先搜尋的話,最多需要約5億次列舉計算

計算機一秒可以進行約1億次計算,所以這個時間是可以接受的。

七,原問題的求解

原問題由於有紅子的限制,所以程式設計起來要複雜一些,但是需要列舉的情況少一些。

這樣,就可以深度優先搜尋求解了,同時,因為局面的數量很有限,所以用動態規劃的備忘錄方法來避免重複工作。

程式碼:

#include <iostream>
#include<stack>
using namespace std;

int r[8192][14];//0表示未知,-1表示死局面,1表示活局面
int st[16] = { 1, 1, 3, 11, 1, 2, 2, 3, 6, 7, 8, 7, 4, 5, 6, 2 };
int en[16] = { 3, 11, 13, 13, 7, 6, 8, 7, 12, 11, 12, 13, 10, 9, 8, 12 };
stack<int>ans;

bool f(int n, int k)
{
	if (n == (n&-n))return true;//只有1個子
	if (r[n][k] < 0)return false;
	int s, e, m;
	for (int i = 0; i < 16; i++)
	{
		s = st[i], e = en[i], m = (s + e) / 2;
		if (m == k)continue;//紅子不能被跳過
		if (!((n >> (13 - m)) & 1))continue;
		if (!(((n >> (13 - s)) & 1) ^ ((n >> (13 - e)) & 1)))continue;
		int nn, kk = k, tem;
		if (k == s || k == e)kk = s + e - k;
		tem = (1 << (13 - s)) + (1 << (13 - e));
		nn = n - (n&tem) + tem - (n&tem) - (1 << (13 - m));
		if (f(nn, kk))
		{
			ans.push(i);
			m = -1;
			break;
		}
	}
	if (m == -1)return true;
	r[n][k] = -1;
	return false;
}

int main()
{
	int n = 0, k;//n表示無顏色局面,k表示紅子位置
	cout << "按照編號\n1    2    3\n  4    5\n6    7    8\n  9    10\n11   12   13\n";
	cout << "即從上到下,從左往右,依次輸入每個格子\n1表示有子,0表示沒有子,全部用空格隔開\n";
	for (int i = 1; i <= 13; i++)
	{
		cin >> k;
		n = n * 2 + k;
	}
	cout << "輸入紅子所在格子的序號(1-13)\n";
	cin >> k;
	for (int i = 0; i < 8192; i++)for (int j = 0; j < 14; j++)r[i][j] = 0;
	while (!ans.empty())ans.pop();
	f(n, k);
	cout << "答案為:(一行表示一次操作,每行2個整數分別代表起點和終點的序號)\n";
	while (!ans.empty())
	{
		int i = ans.top();
		ans.pop();
		cout << st[i] << "   " << en[i] << endl;
	}
	return 0;
}

示例:




相關推薦

Hopping dots 獨立鑽石變種

前言:這篇文章,我想完整的討論一個遊戲,叫Hopping dots,被翻譯為邏輯難題。關鍵詞:獨立鑽石棋、深度優先搜尋、可能性分析、狀態壓縮、動態規劃的備忘錄方法一,APK下載連結我的版本:Hoppin

IQ使命 Antwerp 安特衛普選寶石放木塊

IQ使命 目錄: 本章規則: 簡單說來規則就是,在n*n的棋盤上放著n種顏色的寶石,每種顏色都有的寶石都有n個, 要選擇一種寶石留下,其他的寶石全部用所給木塊覆蓋(所給木塊的總長

poj 1837 天平問題01背包變種

變量 cst 距離 新的 out 貢獻 不同的 () space 題意:給你n個掛鉤,m個砝碼,要求砝碼都用上,問有多少中方案數 題解:對於這道題目的狀態,我們定義一個變量j為平衡度,當j=0的時候,表明天平平衡。定義dp[i][j]表達的含義為使用前n個砝碼的時候,平衡度

B. Fox And Two Dots迷宮找環問題

題目連結:http://codeforces.com/problemset/problem/510/B B. Fox And Two Dots a mobile puzzle game called "Two Dots". The basic levels are played on a b

#100-【最小生成森林最小生成樹變種】灌水

#100祭! Description Farmer John已經決定把水灌到他的n(1<=n<=300)塊農田,農田被數字1到n標記。把一塊土地進行灌水有兩種方法,從其他農田飲水,或者這

Tic Tac Toe 三連遊戲

Description Tic Tac Toe is a child's game played on a 3 by 3 grid. One player, X, starts by placing an X at an unoccupied grid position

CF510B Fox And Two Dots搜索圖形環

sid ace sys graph mac graphic col least 100% B. Fox And Two Dots time limit per test 2 seconds memory limit per test 256 megaby

最新最全張家界旅遊您必須知道的張家界

麗江 註意 四面 歷史 國際 基本上 我們 強制 微信 2019年最新最全面的張家界旅遊攻略,有我在手,說走就走,值得您收藏和分享…… 還在網上到處搜索有關張家界旅遊的攻略事項嗎? 還在篩選哪個才是最新最值得參考嗎? 還在為去張家界旅遊不知如何玩起嗎? 不用找了,就在這裏…

HMM隱馬爾可夫模型HMM

隱馬爾可夫模型 (Hidden Markov Model,HMM) 最初由 L. E. Baum 和其它一些學者發表在一系列的統計學論文中,隨後在語言識別,自然語言處理以及生物資訊等領域體現了很大的價值。平時,經常能接觸到涉及 HMM 的相關文章,一直沒有仔細研究過,都

雲棲社群雲棲號團隊部落格【2018版】

雲棲社群雲棲號是什麼? 這是一個為技術團隊打造的專區(小站),團隊成員的技術文章將在這裡彙總,可以幫助團隊沉澱優質技術內容、打造技術品牌和影響力等。 雲棲號申請條件 點選https://yq.aliyun.com/teams頁面右側的【申請雲棲號】,按照要求填寫郵件內容,社群管理員稽核後即可開通。 申請

IQ使命2 Tokyo 東京跳棋

IQ使命2  目錄: 本章規則: 白子可以跳過1個棋子,黑子可以跳過1個或多個棋子,把所有的棋子都放進洞裡即可 (1) (2) 每個洞的周圍有2-4個格子,其中有0-4個格子裡面有

IQ使命 Marrakech 馬拉喀什六邊形圖案

IQ使命 目錄: 本章規則: 就是選擇一個球(有7個選擇),點選這個球它周圍的6個球就會順時針轉動60度完成一次輪換,最終要得到給定的圖樣。 編號: 因為只有7種操作,分別是點

IQ使命2 Barcelona 巴塞羅那色塊覆蓋

IQ使命2  目錄: 本章規則: 就是要用所給的木塊覆蓋陰影區域,而且相鄰的木塊不能同色 (1) (2) (3) (4) (5) (6) 除了第(1)(

IQ使命2 Tikal 提卡爾旋轉的通道

IQ使命2  目錄: 本章規則: 把硬幣移入洞內,如果移動到帶有旋轉箭頭的格子,這個格子就會按照箭頭的方向旋轉90° (1) 右上下右 (2) 紅色的格子會全部一起旋轉 左下上左上 (3) 左下右左上下右右右上左 (4) 左上下左下上右下 (5)

IQ使命 London 倫敦一筆畫

IQ使命 目錄: 本章規則: 就是一筆畫 一筆畫問題本身非常簡單,如果加了一些特殊規則才會變得複雜,如點選開啟連結 本章只是最基本的一筆畫問題,所以很簡單,只需要2步。 第一步,

隱馬爾可夫模型HMM

上邊的圖示都強調了 HMM 的狀態變遷。而下圖則明確的表示出模型的演化,其中綠色的圓圈表示隱藏狀態,紫色圓圈表示可觀察到狀態,箭頭表示狀態之間的依存概率,一個 HMM 可用一個5元組 { N, M, π,A,B } 表示,其中 N 表示隱藏狀態的數量,我們要麼知道確切的值,要麼猜測該值,M 表示可觀測狀態的

IQ使命 Luxor 埃及盧克索華容道

IQ使命 目錄: 華容道分類: 華容道可以分三大類,一類是正宗的三國華容道,一類是汽車華容道,還有其他變種華容道。 (1)三國華容道 三國華容道有5行4列,有曹操、五虎將和4個士

【分享】PRIMAL×HEARTS1+2 (プライマルハーツ‐【日文硬碟版】帶全CG存檔&日文+開啟存檔補丁

春天,那是邂逅的季節。 站在櫻花樹下,我對即將轉入的新學園的生活感到期待不已。 沒錯,直到穿過校門的幾分鐘之前我都是這麼想的—— 「就決定是注重傳統的月花會吧!」 「尋求革新的天道會才更加有趣哦♪」 我轉入的間ノ島學園中同時存在著兩個學生會,兩者間總是在競爭著。 雙方的支援率正好五五開,而會打破這個平衡的,

IQ使命 Monte Carlo 蒙特卡洛推箱子

IQ使命 目錄: 本章規則: 規則裡面有3點,(1)白的和紅的可以推白的和黃的(2)黃的可以跳過任意箱子(3)紅的不能被推動 (1) (2) (3)

LightOJ 1356 Prime Independence質因數分解+最大獨立集+Hopcroft-Carp

target pri 建圖 spa dfs cto rim %d 最大獨立集 http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1356 題意: 給出n個數,問最多能選幾個數,