特种部队

特种部队

 时间限制: 1 s
 空间限制: 64000 KB
题目描述 Description

某特种部队接到一个任务,需要潜入一个仓库。该部队士兵分为两路,第一路士兵已经在正面牵制住了敌人,第二路士兵正在悄悄地从后方秘密潜入敌人的仓库。
当他们到达仓库时候,发现这个仓库的锁是一把很诡异的电子锁,上面是一排按钮,每个按钮上都有一个数字。10 秒钟后,总部返回了该锁的技术信息。要解开这把锁,首先要从左边的第一个按钮开始向右按动,中间可以跳过某些按钮,按动到最右边的按钮后,反向向左按动。最终,每个按钮都要按且仅按一次。每两个相邻按钮上数字之差的总和的最小值,便是解开这把锁的密码。
作为一支装备精良的特种部队,必须要在最短的时间内完成任务,解开这把锁,潜入仓库。

输入描述 Input Description

第一行是一个n(2 <= n <= 1000)表示共有n 个按钮。
第二行是n 个正整数,代表从左至右各按钮上的数字,数值均不超过2000。

输出描述 Output Description

只有一个数,为这把锁的密码。

样例输入 Sample Input

5
1 2 3 4 5

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

2 <= n <= 1000,数值不超过2000

题目链接:http://www.rqnoj.cn/problem/204


 动态规划。

题目分析:首先题目要求来回两次选数,这个来回非常恶心,所以我们可以考虑把题目转化为从终点开始,向起点选两次数。
状态设计:设dp[i][j]为当前两次选数分别选到i点和j点的最小答案,且min(i,j)到n的数都被选过一次。
状态转移:状态设计出来,转移就比较简单了,每次(i,j)只会向(min(i,j)-1,j)和(i,min(i,j)-1)转移。
#include<bits/stdc++.h>
#define N 2005
using namespace std;
int a[N];
int dp[N][N];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=0;i<=n+1;i++)
    for(int j=0;j<=n+1;j++)dp[i][j]=INT_MAX/2;
    
    dp[n][n]=0;
    
    for(int i=n;i>=1;i--)
    for(int j=n;j>=1;j--)
    {
        if(min(i,j)-1!=j&&min(i,j)>1)
        {
            dp[min(i,j)-1][j]=min(dp[min(i,j)-1][j],dp[i][j]+abs(a[i]-a[min(i,j)-1]));
        //    dp[min(i,j)-1][j]=min(dp[min(i,j)-1][j],dp[i][j]+abs(a[j]-a[min(i,j)-1]));
        }
        
        if(min(i,j)-1!=i&&min(i,j)>1)
        {
        //    dp[i][min(i,j)-1]=min(dp[i][min(i,j)-1],dp[i][j]+abs(a[i]-a[min(i,j)-1]));
            dp[i][min(i,j)-1]=min(dp[i][min(i,j)-1],dp[i][j]+abs(a[j]-a[min(i,j)-1]));
        }
    }
    
    int ans=INT_MAX/2;
    for(int i=1;i<=n;i++)ans=min(ans,dp[1][i]),ans=min(ans,dp[i][1]);
    
    printf("%d
",ans);
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/tian-luo/p/9741074.html