蜘蛛牌
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2716 Accepted Submission(s): 1157
每組數據有一行,10個輸入數據,數據的範圍是[1,10],分別表示A到10,我們保證每組數據都是合法的。
/*
思路:做題時分類顯示是搜索
1.但我感覺用貪心更好。更高效
10肯定不動,那麼9動之前是8連上去還是9過去後再連呢,對於8後的7也是這樣考慮
容易知道,一個數例如1,他要麼去2默認的位置,要麼去2變後的位置,只能這兩種
於是就貪心就行了,但是這種做法不對,如果出現一個數i到i+1和i+2的距離相同,那麼他
是先去i+1還是i+2呢,又分了情況
2.於是感覺用動態規劃也能做
dp[i]=min(dp[i],abs(book[i]-book[j])) j=[i+1,10];
但是發現不對,例如5 2 3 10 8 6 4 7 1 9
9去10肯定,按照狀態方程,8是去10,那麼問題來了,按照狀態方程,7應該是去9的,
然而8是去10,所以不對
3.日了狗了
*/
//轉載網上代碼:
//思路:將所有狀況進行一次DFS
#include <stdio.h>
#include <string.h>
int a[15],vis[15],ans;
int abs(int x)
{
if(x<0)
return -x;
return x;
}
void dfs(int cnt,int sum)
{
int i,j;
if(sum>=ans)
return ;
if(cnt == 9) //每次選擇一個變換,9次結束
{
ans = sum;
return ;
}
for(i = 1;i<10;i++) //第cnt次選擇任意一張牌要疊上去
{
if(!vis[i])
{
vis[i] = 1; //標記
for(j = i+1;j<=10;j++)
//選擇要疊到哪張牌上 這裏的意思是從i+1這張牌開始選
//這張牌要沒被移動過,如果被移動過,那麼他就是去了更高牌的位置上
{
if(!vis[j])
{
dfs(cnt+1,sum+abs(a[i]-a[j])); //進入第cnt次選擇
break;
//所以只要找到一次,遞歸後就跳出,因爲剛找到的這張牌是沒移動過
//你不能去下一個更大的牌,接不下去
}
}
vis[i] = 0; //回溯
}
}
}
int main()
{
int t,i,x;
scanf("%d",&t);
while(t--)
{
for(i = 1;i<=10;i++)
{
scanf("%d",&x);
a[x] = i;//牌面爲x的牌在第i個位置
}
memset(vis,0,sizeof(vis));
ans = 10000000;
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}
/*
1
5 2 3 10 8 6 4 7 1 9
*/