在魔方風靡全球之後不久,rubik先生發明了它的簡化版——魔板。魔板由8個同樣大小的方塊組成,每個方塊顏色均不相同,可用數字1-8分別表示。任一時刻魔板的狀態可用方塊的顏色序列表示:從魔板的左上角開始,按順時針方向依次寫下各方塊的顏色代號,所得到的數字序列即可表示此時魔板的狀態。例如,序列(1,2,3,4,5,6,7,8)表示魔板狀態為:
1 2 3 4
8 7 6 5
對於魔板,可施加三種不同的操作,具體操作方法如下:
a: 上下兩行互換,如上圖可變換為狀態87654321
b: 每行同時迴圈右移一格,如上圖可變換為41236785
c: 中間4個方塊順時針旋轉一格,如上圖可變換為17245368
給你魔板的初始狀態與目標狀態,請給出由初態到目態變換數最少的變換步驟,若有多種變換方案則取字典序最小的那種。
看到最小狀態轉移步驟自然的想到bfs,所以需要對魔板的狀態進行hash處理,這裡狀態數量有8!種,康托展開能夠將每種排序都轉換成乙個唯一的序列號,而且全部狀態的總序列號恰好在n!內分布。
以下貼網上大佬們的康托展開介紹:
所以運用康托展開+bfs就能搞定從12345678序列轉移到任意序列所需的狀態數最少。
但題目給的是乙個初始狀態和乙個目標狀態,所以我們需要建立hash對應陣列m,將初始狀態對應成12345678序列,進行求解即可》
#include #define ll long long
using namespace std;
string ans[45000];
int f[10], m[10];
void cantor(int s, ll num, int k); //0到k-1,表示是否出現過
for (int i = 0; i < k; i++)
} }}void inv_cantor(int s, ll &num, int k)
}inline void gao(int s,char &ch)
break;
case 'c':swap(s[6],s[1]);swap(s[5],s[6]);swap(s[2],s[5]);
break;
}}void init() }}
int main()
for(int i=0;i<8;i++)m[n[i]-'0']=i+1;
for(int i=0;i<8;i++)k[i]=m[t[i]-'0'];
inv_cantor(k,num,8);
cout<
}return 0;
}
HDU1430 魔板 康托展開
problem description 在魔方風靡全球之後不久,rubik先生發明了它的簡化版 魔板。魔板由8個同樣大小的方塊組成,每個方塊顏色均不相同,可用數字1 8分別表示。任一時刻魔板的狀態可用方塊的顏色序列表示 從魔板的左上角開始,按順時針方向依次寫下各方塊的顏色代號,所得到的數字序列即可表...
hdu 1430 魔板 康拓展開 對映優化
給定三種操作,將排列a轉化為排列b,求最少步驟。這種題目可以只跑一次bfs,比如只跑 12345678 那麼如果遇到 23456781 某個字串呢?因為每乙個數字都是等價的,我們可以把2對映為1,3對映成2,以此類推。這樣就可以用 12345678 跑出來的操作序列了。include include...
康拓展開和逆康拓展開
康托展開就是一種特殊的雜湊函式 把乙個整數x展開成如下形式 x a n n a n 1 n 1 a 2 2 a 1 1 其中,a為整數,並且0 a表示1,2,3,n的排列如 按從小到大排列一共6種,就是123 132 213 231 312 321 代表的數字 1 2 3 4 5 6 也就是把10進...