北方大学 ACM 多校训练赛 第十五场 蜘蛛牌A

题目描述

XCX最近迷上了玩蜘蛛牌。蜘蛛牌是windowsxp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比它大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌也跟着一起移动,游戏的目的是将所有的牌按同一花色从小到大排好。为了简单起见,我们的游戏只有同一花色的牌,但是这样XCX又觉得太简单了,于是他把牌数增加到了n(1<=n<=100),牌随机的在一行上展开,编号从1到n,把第i号上的牌移到第j号牌上,移动距离为abs(i-j),现在你要做的是求出完成游戏的最小移动距离。

输入描述

第一行T(1<=T<=1010)代表T组数据。每组数据包括两行,第一行是一个数字n,代表有n张牌,第二行有n个数字:为1…n的一种排列。

输出描述

最小移动距离

样例输入
1
10
3 10 4 2 5 9 1 8 6 7
样例输出
16
题解:

采用区间动态规划的方式,但是直接进行区间DP是没有任何意义的,因此需要对数列进行变化一下,我们进行dp的区间[a,b]定义为高度为a到高度为b的纸牌叠加到一起,所需要的最少距离和。在一开始,我们定义数组arr[x]中存储的是高度为x的纸牌所在的位置。那么状态转移就可以写成:dp[a][b] = dp[a][j] + dp[j+1][b] + abs(arr[b]-arr[j])


代码:

#include<bits/stdc++.h>
using namespace std;

int a[105],n;
int dp[105][105];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            a[x]=i;
        }
        for(int k=2;k<=n;k++)
        {
            for(int i=1;i<=n-k+1;i++)
            {
                int l=i,r=i+k-1;
                dp[l][r]=1e9+7;
                for(int j=l;j<=r-1;j++)
                    dp[l][r]=min(dp[l][r],dp[l][j]+dp[j+1][r]+abs(a[r]-a[j]));
            }
        }
        printf("%d\n",dp[1][n]);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值