蜘蛛牌
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3949 Accepted Submission(s): 1706
Problem Description
蜘蛛牌是windows xp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比她大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌也跟着一起移动,游戏的目的是将所有的牌按同一花色从小到大排好,为了简单起见,我们的游戏只有同一花色的10张牌,从A到10,且随机的在一行上展开,编号从1到10,把第i号上的牌移到第j号牌上,移动距离为abs(i-j),现在你要做的是求出完成游戏的最小移动距离。
Input
第一个输入数据是T,表示数据的组数。
每组数据有一行,10个输入数据,数据的范围是[1,10],分别表示A到10,我们保证每组数据都是合法的。
每组数据有一行,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
思路:写在注释上了;
代码:
//这个题目不难,我的思路是 重建了一个图,map,使得没个点到每个点之间都有一条边,的权为他们的位置相减。这样可以节约很多时间
//然后就是dfs跑,用b数组 保存每个位置有哪些牌这里只用保存第一个和最后一个就行,其余的不用管。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int a[11];
int b[11][2];
int map[11][11];
int anf;
void dfs(int x,int y,int sum)
{
sum+=map[x][y];
b[y][1]=b[x][1];//移动了变换;
b[x][0]=0;
b[x][1]=0;
//printf("%d %d %d %d %d\n",x,y,sum,b[y][0],b[y][1]);
if(sum>anf) return ;
if(b[10][0]==10&&b[10][1]==1) {anf=sum;return ;}
//printf("aa\n");
for(int i=1;i<=10;i++)
{
if(b[a[i]][0]==0) continue;
if(b[a[i]][0]==10) continue;
int u;
for(int j=1;j<=10;j++)
{
if(b[j][1]==a[i]+1) {u=j;break;}
}
// printf("%d \n",u);
int t0,t1,t3,t4;
t0=b[a[i]][0],t1=b[a[i]][1];//这里用来回溯
t3=b[u][0],t4=b[u][1];
// printf("%tt %d %d %d %d \n",t0,t1,t3,t4);
dfs(a[i],b[u][0],sum);
b[a[i]][0]=t0,b[a[i]][1]=t1;
b[u][0]=t3,b[u][1]=t4;
}
return ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{ b[0][0]=b[0][1]=0;
for(int i=1;i<=10;i++)
{
scanf("%d",&a[i]);
b[i][0]=i;
b[i][1]=i;
}
memset(map,0,sizeof(map));
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
{
map[a[i]][a[j]]=abs(j-i);
map[a[j]][a[i]]=abs(j-i);
}
}
/*for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
printf("%d ",map[i][j]);
printf("\n");
}*/
anf=999999999;
dfs(0,0,0);
printf("%d\n",anf);
}
}