hdu1584(状态压缩DP)

蜘蛛牌

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2068    Accepted Submission(s): 844


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
 
Author
xhd
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  1430 1732 1429 1495 1016 
 设d[s]表示s状态排好序所需要的最小花费,那么每次选择两个数,一个较大数,一个较小数,并且较大数与较小数的差值是s
这个状态里所有数中差值最小的,每次枚举这两个数,可以包含所有可能出现的情形。
因为题目要求是较小数要放在比它大一的数上面,然而会出现这种情形,就是放好几次之后
再放,就不会只能放在大一的牌上面上了。所以d[s]=min(d[s],d[s ^ (1<<ID)]+dist[i][id]); ID表示选择的两个数中较小的数,
dist[i][ID]表示将ID放在i上面所需要的花费。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define maxn 20
#define inf   0x3f3f3f3f3f3f3f3f
using namespace std;
int d[1<<maxn]; //
int a[maxn];
int n;
int Min(int x,int y)
{
    if(x<=y)
        return x;
    else
        return y;
}
void init()
{
    for(int i=0;i<(1<<maxn);i++)
    {
        d[i]=inf;
    }
    for(int i=0;i<20;i++)
        d[(1<<i)]=0;

}
int dist[maxn][maxn];
int p[maxn];
int pos[maxn];
void work()
{
    for(int s=3;s<(1<<10);s++)
   {
      int i,j;
      for(i=0;i<10;i++)
       if(s & (1<<i))
       {
         int MIN=inf,ID=-1;
         for(j=0;j<10;j++)
         {
            if(s & (1<<j))
           {
              if(i-j<=0)
                continue;
              if(i-j<=MIN)
              {
                 MIN=i-j;
                 ID=j;
              }
           }
         }
         if(ID!=-1)
            d[s]=Min(d[s],d[s ^ (1<<ID)]+dist[i][ID]);
       }
   }
}
void input()
{
    for(int i=0;i<10;i++)
    {
         scanf("%d",&a[i]);
         a[i]--;
         pos[a[i]]=i;
    }
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<10;j++)
        {
            dist[i][j]=abs(pos[i]-pos[j]);
        }
       // cout<<endl;
    }

}
int main()
{
   // freopen("test.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
      init();
      input();
     // solve();
      work();
      printf("%d
",d[(1<<10)-1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xianbin7/p/4757960.html