hdu1584蜘蛛牌解題報告---搜尋(深搜 & 回溯)
阿新 • • 發佈:2018-12-06
蜘蛛牌
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6100 Accepted Submission(s): 2546
Problem Description
蜘蛛牌是windows xp作業系統自帶的一款紙牌遊戲,遊戲規則是這樣的:只能將牌拖到比她大一的牌上面(A最小,K最大),如果拖動的牌上有按順序排好的牌時,那麼這些牌也跟著一起移動,遊戲的目的是將所有的牌按同一花色從小到大排好,為了簡單起見,我們的遊戲只有同一花色的10張牌,從A到10,且隨機的在一行上展開,編號從1到10,把第i號上的牌移到第j號牌上,移動距離為abs(i-j),現在你要做的是求出完成遊戲的最小移動距離。
Input
第一個輸入資料是T,表示資料的組數。
每組資料有一行,10個輸入資料,資料的範圍是[1,10],分別表示A到10,我們保證每組資料都是合法的。
Output
對應每組資料輸出最小移動距離。
Sample Input
1
1 2 3 4 5 6 7 8 9 10
Sample Output
9
很有價值的一道全排列搜尋,既要考慮回溯的位置,又要處理每張牌的移動情況
AC Code:
#include <cstdio> #include <cmath> #include<algorithm> #include<iostream> #include<cstring> #include<map> #include<queue> #include<climits> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 using namespace std; typedef long long ll; static const int MAX_N = 1e6 + 5; bool vis[12]; int vv[12]; int res; void dfs(int step, int sum){ if(step == 9){ res = min(res, sum); return; } if(step > 9) return; for(int i = 1; i < 10; i++){ if(vis[i]) continue; vis[i] = true; //移動面值為i的牌 for(int j = i + 1; j <= 10; j++){ if(vis[j]) continue; //說明面值為i + 1的牌已經擺在更大面值牌的下面了,把i放在這張更大面值的牌j下面 dfs(step + 1, sum + abs(vv[i] - vv[j])); break; //找到這張最大面值牌後跳出迴圈 } vis[i] = false; //回溯要放這裡 } } int main(){ int T; scanf("%d", &T); while(T--){ res = 9999; for(int i = 1; i <= 10; i++){ int v; scanf("%d", &v); vv[v] = i; //面值為v的牌的位置 } dfs(0, 0); printf("%d\n", res); } return 0; }