dfs_蜘蛛牌 HDU - 1584
阿新 • • 發佈:2018-12-02
這道題,讓我把dfs突然搞不懂了,讓我很糊塗。只知道每一次都回溯。
題目:
蜘蛛牌是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
題目大意:
蜘蛛紙牌大家都玩過,就是看怎麼移動紙牌,最後的到的移動步數最小
演算法:
dfs (剪枝)
程式碼:
#include<iostream> #include<cmath> using namespace std; int a[15],b[15],ans; //陣列a用來儲存牌的位置,陣列b作為標記陣列 void dfs(int num,int sum) { int i,j; if(sum>ans)//如果此時移動距離已經大於已經得到的最短距離,就返回 return; if(num==9)//如果移動九次都沒有大於已經得到的最短距離,就更新最短距離 { ans=sum; return; //回溯 } for(i=1;i<=10;i++) { if(!b[i])//如果i還沒有放入,給它找位置 { b[i]=1; //標記已經移動 for(j=i+1;j<=10;j++) //j=i+1 因為i要放到比他大的牌的下邊 if(!b[j]) //例如現在移動牌3,發現b[4]、b[5]都是1(4和5已經移動過了),也就是說4,5已經放到了6的下邊 //所以將3放到6的下邊 { dfs(num+1,sum+abs(a[i]-a[j])); break; } b[i]=0;//回溯 } } } int main() { int n,i,j; cin>>n; while(n--) { for(i=1;i<=10;i++) { cin>>j; a[j]=i;//牌號為j的撲克的位置是i } ans=100000000; dfs(0,0); cout<<ans<<endl; } return 0; }
解析:
一定要注意 a[j]=i 表示 牌號為j的撲克的位置是i 。
採用dfs 每次都列舉十張牌,看他可以放到哪一個位置上。
例如現在移動牌3,發現b[4]、b[5]都是1(說明4和5已經移動過好了),也就是說4,5已經放到了6的下邊,那麼3可以直接放到6的下邊,也就是6.5.4.3