1. 程式人生 > >dfs_蜘蛛牌 HDU - 1584

dfs_蜘蛛牌 HDU - 1584

這道題,讓我把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