蜘蛛牌
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5125 Accepted Submission(s): 2184
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
暴力搜索 1560ms
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
typedef long long ll;
int n;
int ans;
int now;
struct node{
int t;
int b;
};
node a[15];
int abs(int x){
if(x<0){
return -x;
}
else{
return x;
}
}
void print(){
for(int i=1;i<=10;i++){
cout<<a[i].t<<" ";
}
cout<<endl;
for(int i=1;i<=10;i++){
cout<<a[i].b<<" ";
}
cout<<endl;
}
void dfs(){
//print();
for(int i=1;i<=10;i++){
if(a[i].t==1&&a[i].b==10){
ans=min(ans,now);
return;
}
}
for(int i=1;i<=10;i++){
if(a[i].t==0)continue;
if(a[i].b!=10){
for(int j=1;j<=10;j++){
if(a[j].t==a[i].b+1){
now+=abs(i-j);
node t1=a[i];
node t2=a[j];
a[j].t=a[i].t;
a[i].t=0;
a[i].b=0;
dfs();
a[i]=t1;
a[j]=t2;
now-=abs(i-j);
}
}
}
}
return;
}
void solve(){
scanf("%d",&n);
while(n--){
for(int i=1;i<=10;i++){
scanf("%d",&a[i].t);
a[i].b=a[i].t;
}
ans=100;
now=0;
dfs();
printf("%d\n",ans);
}
return;
}
int main(){
solve();
return 0;
}
剪枝187ms
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
typedef long long ll;
int n;
int ans;
int now;
struct node{
int t;
int b;
};
node a[15];
int abs(int x){
if(x<0){
return -x;
}
else{
return x;
}
}
void print(){
for(int i=1;i<=10;i++){
cout<<a[i].t<<" ";
}
cout<<endl;
for(int i=1;i<=10;i++){
cout<<a[i].b<<" ";
}
cout<<endl;
}
void dfs(){
//print();
for(int i=1;i<=10;i++){
if(a[i].t==1&&a[i].b==10){
ans=min(ans,now);
return;
}
}
for(int i=1;i<=10;i++){
if(a[i].t==0)continue;
if(a[i].b!=10){
for(int j=1;j<=10;j++){
if(a[j].t==a[i].b+1){
if(now+abs(i-j)>=ans)continue;
now+=abs(i-j);
node t1=a[i];
node t2=a[j];
a[j].t=a[i].t;
a[i].t=0;
a[i].b=0;
dfs();
a[i]=t1;
a[j]=t2;
now-=abs(i-j);
}
}
}
}
return;
}
void solve(){
scanf("%d",&n);
while(n--){
for(int i=1;i<=10;i++){
scanf("%d",&a[i].t);
a[i].b=a[i].t;
}
ans=100;
now=0;
dfs();
printf("%d\n",ans);
}
return;
}
int main(){
solve();
return 0;
}
区间dp 0ms
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
typedef long long ll;
const int INF=1e9;
int n;
int a[11];
int dp[11][11];
int abs(int x){
return x<0?-x:x;
}
void print(){
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++){
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
}
void solve(){
scanf("%d",&n);
while(n--){
for(int i=1;i<=10;i++){
int x;
scanf("%d",&x);
a[x]=i;
}
for(int i=1;i<=10;i++){
dp[i][i]=0;
}
//print();
for(int i=9;i>=1;i--){
for(int j=i+1;j<=10;j++){
int now=1e9;
for(int k=i;k<j;k++){
now=min(now,dp[i][k]+dp[k+1][j]+abs(a[k]-a[j]));
}
dp[i][j]=now;
}
}
//print();
printf("%d\n",dp[1][10]);
}
return;
}
int main(){
solve();
return 0;
}