HDU 1584 蜘蛛牌(经典深搜dfs)

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
深搜做着是真的难呀,比赛的时候就没看出来,比赛后去看题解也是想了很久才想通了,感觉回溯那一块有点难理解,感觉自己对dfs这块还是有点迷,不过bfs这种思想真的很神奇呀,其实很多人都是卡在了过程那段,会去想这个过程那个过程怎么实现,导致越想越迷,但是如果一直想不通的话说明你对dfs理解不够透彻。基本上每道dfs题都少不了剪枝和递归,直到最后,还有就是回溯那个环节,当然这道题也不例外

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
int v[15],mark[15];
int ans;
void dfs(int num,int sum)//num表示的是循环的次数,num表示的是移动的距离之和
{
    if(sum>=ans)
    {
        return ;  //剪枝,ans表示的是最少步数,一旦sum>ans就表示这一次回溯不可能是最优解,所以直接返回
    }
    if(num == 9) //因为这是9层的递归,1只能移到2上,2只能移到3上,同理,最后也只能移动9次,所以9次就表明移完了
    {
        ans=sum;  //如果移动了9次而没有被剪枝剪掉就表明这次的解比上次更小
        return ;
    }

    for(int i=1;i<10;i++) //因为最后的话10这个位置没法向别的位置移动了,所以就判断9次
    {
        if(!mark[i])
        {
             mark[i]=1;
              for(int j=i+1;j<=10;j++) //表示的是从i移动到j上可以从9号移到10上,所以包含10
              {
                if(!mark[j])
                {
                    dfs(num+1,sum+abs(v[j]-v[i]));//别写成sum=sum+abs(v[j]-v[i]),因为会改变sum的值
                    break;//直到找到下一个后结束for循环,比如某一布回溯到1了,那肯定要先找2,发现2被标记了,那肯定2去找过3了,此时2应该在3上面,然后你去找3,此时3可能在4上面也可能没在4上面,如果在4上面你就去找4,如果没在4上面你就可以把1放到3上面了,放后3上面就成了3,2,1
                }
              }
           mark[i]=0; //进行回溯
        }

    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int i;
        for(int a=1;a<=10;a++)
        {
            scanf("%d",&i);
            v[i]=a; //表示i这个数在a这个位置上
        }
        memset(mark,0,sizeof(mark));
         ans=100000000;
         dfs(0,0);
         printf("%d\n",ans);
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/weixin_44122831/article/details/88989960