JZOJ1444 交換 推薦

2021-07-15 03:20:26 字數 1843 閱讀 7006

description

給定1到n的乙個排列,再給定一些允許的交換方法,要求用最少的交換次數把該排列變為1,2,3,,,n。

input

第一行包含兩個整數n(1<=n<=12)和m(1<=m<=n*(n-1)/2),表示序列的長度以及允許的交換方案。

第二行輸入1到n個初始排列情況。

接下來m行,每行兩個整數a和b描述乙個允許的交換方案,表示允許把當前排列中的第a個數和第b個數進行交換,保證a和b不相同。

輸入保證一定存在解。

output

輸出乙個整數表示最少需要的交換次數。

sample input

輸入1:

2 12 1

1 2輸入2:

3 22 1 3

1 32 3

輸入3:

5 51 2 3 4 5

1 52 5

1 41 1

3 5sample output

輸出1:

輸出2:

輸出3:

觀察資料範圍,發現這裡的n很小,也許可以用暴力來處理。

但是,如果用暴力的話,會出現很多重複狀態,而且效率不高。

開始的起始狀態我們是知道的,最終轉移到的狀態我們也是知道的,而且每種操作的改變對於正著做和反著做都是相同的。

不過,我們如何記錄它的狀態?

開應該12維的布林陣列是不太科學的,

因為n很小只用12,而且

1213

=106993205379072

這個數是可以用long long存的下的。

那麼我們就將每乙個序列看成應該12進製的數,再將它轉換成為應該10進製數。

這樣,我們就可以將每乙個序列變成乙個數。

然而,這裡可能出現的狀態不是很多,我們可以用hash表來儲存和判重。

#include 

#include

#include

#include

#include

#include

#include

#define ll long long

#define mo 1000007

using

namespace

std;

ll ha[mo];

bool bz[mo];

int g[mo];

ll data[3*mo],da1[3*mo],z[15],s;

int a[15],t[15],f[15],cz[150][2];

int n,m,l,now;

int hash(ll x)

ll zz()

void aa(ll x)

}int main()

for(int i=1;i<=m;i++)

scanf("%d%d",&cz[i][0],&cz[i][1]);

da1[1]=zz();

l=hash(da1[1]);

ha[l]=da1[1];

bz[l]=1;

memcpy(t,a,sizeof(t));

data[1]=zz();

l=hash(data[1]);

ha[l]=data[1];

if(da1[1]==data[1])

int i=0,j=1,p=0,q=1;

while((ifor(int k=1;k<=m;k++)

}else

}p++;

aa(da1[p]);

now=g[hash(da1[p])];

for(int k=1;k<=m;k++)

}else }}

}

14 4 選單功能

選單功能就是與使用者的溝通介面。1 在workermanager.h標頭檔案中新增show menu 成員函式。class workermanager 2 在workermanager.cpp中實現show menu 成員函式。其實這個函式就是在螢幕中把選單介面列印出來,沒什麼技術含量。顯示選單 v...

14 4 執行緒的通訊

執行緒通訊 乙個執行緒完成自己的任務時,就要通知另外乙個執行緒去 例子就是生產者與消費者關係 wait 等待。如果執行緒執行了wait方法,那麼該執行緒會進入等待的狀態 notify 喚醒等待的執行緒 注意 1 wait和notify方法是屬於objeck類的。2 wait和notify方法必須是要...

南陽144 某種序列

時間限制 3000 ms 記憶體限制 65535 kb 難度 4 描述 數列a滿足an an 1 an 2 an 3,n 3 編寫程式,給定a0,a1 和 a2,計算a99 輸入 輸入包含多行資料 每行資料報含3個整數a0,a1,a2 0 a0,a1,a2 100000000 資料以eof結束 輸出...