题意:
蜘蛛牌是windows xp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比她大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌也跟着一起移动,游戏的目的是将所有的牌按同一花色从小到大排好,为了简单起见,我们的游戏只有同一花色的10张牌,从A到10,且随机的在一行上展开,编号从1到10,把第i号上的牌移到第j号牌上,移动距离为abs(i-j),现在你要做的是求出完成游戏的最小移动距离。
输入:
第一个输入数据是T,表示数据的组数。
每组数据有一行,10个输入数据,数据的范围是[1,10],分别表示A到10,我们保证每组数据都是合法的。
输出:
对应每组数据输出最小移动距离。
a[i] 表示编号为i的牌放在了a[i]这个位置上
b[i] 存储a[i]最原先的位置,便于回溯
分析:最后一定是移动了9次牌的位置(每个一次),因为10号牌是不需要移动的
若vis[i]=false,则第i号牌没有移动过,则a[i]一定等于b[i]
若vis[i]=true,则第i号牌移动过,a[i]不等于b[i]
这道题有一个要注意的地方:
在把i放到i+1下面的时候,a[i]=a[i+1],
但此时跟着第i号牌的牌也要同时=a[i+1],所以回溯的时候也要把他们恢复过来
而且比如说4要移到5的位置上,假设5在这之前已经移到了6的上面,那4就要移到6的位置上,而不是5的位置
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 using namespace std; 5 const int inf=0x3f3f3f3f; 6 bool vis[12]; 7 int n; 8 int ans; 9 int a[12]; 10 int b[12]; 11 void dfs(int cnt,int sum,int dep) 12 { 13 vis[cnt]=true; 14 for(int j=1;j<=cnt;j++) 15 if(a[j]==b[cnt]) 16 a[j]=a[cnt+1]; 17 if(dep==9&&sum<ans) 18 { 19 ans=sum; 20 return ; 21 } 22 if(sum>=ans||dep==9) 23 return ; 24 25 for(int i=1;i<10;i++) 26 { 27 if(!vis[i]) 28 { 29 dfs(i,sum+abs(a[i]-a[i+1]),dep+1); 30 vis[i]=false; 31 for(int j=1;j<=i;j++) 32 if(a[j]==a[i+1]) 33 a[j]=b[i]; 34 } 35 } 36 return ; 37 } 38 int main() 39 { 40 int test; 41 scanf("%d",&test); 42 while(test--) 43 { 44 int u,w=1; 45 for(int i=1;i<=10;i++) 46 { 47 scanf("%d",&u); 48 a[u]=w++; 49 } 50 for(int i=1;i<=10;i++) 51 b[i]=a[i]; 52 ans=inf; 53 memset(vis,false,sizeof(vis)); 54 for(int i=1;i<10;i++) 55 { 56 dfs(i,abs(a[i]-a[i+1]),1); 57 vis[i]=false; 58 a[i]=b[i]; 59 60 } 61 printf("%d\n",ans); 62 } 63 return 0; 64 }
时间: 2024-10-25 10:09:08