HDU 1430(康拓展開hash)

2021-08-21 21:17:33 字數 1425 閱讀 6069

在魔方風靡全球之後不久,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進...