poj 1925 Spiderman 动态规划

  因为 除了终点外,中途点 位置 高度皆为 Y[1], 我们可以通过 横坐标唯一确定当前状态

  所以 定义状态:

     DP(I,K)  表示经过 第I栋 Building 移动到 K位置,最小 swap次数

  则 转移方程为:

    

  注意到,  因为我们是从  I = 1, 2, 3. ... ,N 顺序处理, dp(k)位置保存着 最优值, 所以第一维 I 我们可以省去

  得到转移方程:

    

  

  对于处理到 第I栋时, 枚举 Xi 到 最大横坐标 ,注意 非法状态的判定, 因为都是顺序处理的,若目前不合法,则后面状态也不合法

解题代码

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

#define MAX(a,b) (a)>(b)?(a):(b)
#define MIN(a,b) (a)<(b)?(a):(b)
typedef long long LL;

const int MAXN = 3000010;
const int N = 5010;
const int inf = 0x3f3f3f3f;

int x[N],y[N];
int dp[MAXN];
int Max,ans, n;

int main()
{
    int T;
    scanf("%d",&T);
    while( T-- )
    {
        scanf("%d", &n);
        Max = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &x[i], &y[i]);
            // 获取能跳跃到最远 横坐标  2*y[1]*y[i] - y[1]^2 = (y[1]-y[i])^2 - y[i]^2     
            Max = MAX( Max, x[i]+1 + (int)(sqrt(2.*y[1]*y[i]-y[1]*y[1])) );
        }
        memset( dp, 0x3f, sizeof(dp) );
        dp[ x[1] ] = 0;
        ans = inf;
        int h = y[1], flag = 0; 
        for(int i = 2; i <= n; i++)
        {
            for(int k = x[i]; k <= Max; k++)
            {
                //因为swap后停下高度始终为 y[1]    
                LL dx = k-x[i], dy = y[i]-h;
                if( dx*dx+dy*dy > 1LL*y[i]*y[i] ) break;
                if( 2*x[i]-k >= x[1] ) // swap的横坐标 大于等于 x[1] 才合法
                    dp[k] = MIN( dp[k], dp[ 2*x[i]-k ]+1 );
                else    break;  // 因为K持续增大,若当前不合法,后面也都不合法    
                if( k >= x[n] && dp[k] < ans )
                {
                    flag = 1; ans = dp[k];    
                }    
            }
        }
        printf("%d\n", flag? ans: -1 );    
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yefeng1627/p/2859785.html