HDU 6365 Shoot Game(区间DP)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/82562802

Description

在二维平面有 n 个障碍物,第 i 个障碍物为高度 H i 处一段连续区间 [ L i , R i ] ,其防御值为 W i ,从原点射击打掉这 N 个障碍物,每次充能 X 就可以打掉这条路径上所有防御值不超过 X 的障碍物,问至少需要多少能量可以消除所有障碍物

Input

第一行一整数 T 表示用例组数,每组用例首先输入一整数 n 表示障碍物数量,最后 n 行每行四个整数 H i , L i , R i , H i

( 1 T 10 , 1 n 300 , 1 H i 10 9 , 10 9 L i , R i 10 9 , 0 W i 10 9 )

Output

输出消除所有障碍物所需的最小能量

Sample Input

2
3
1 1 2 2
2 -1 1 4
3 -2 -1 3
3
1 -1 1 2
2 -1 1 3
3 0 2 0

Sample Output

6
3

Solution

显然只用考虑从原点到端点的这 2 n 条射线即可,如果要清除一个从原点开始的扇形区域,那么必然要处理掉防御值最大的那个障碍物,以此可以区间 D P 求解

2 n 条射线按极角排序并离散化为 1 ~ 2 n ,以 d p [ l ] [ r ] 表示处理掉第 l 条射线与第 r 条射线围成区域内所有障碍物所需要最小能量,假设该区间内障碍物的防御值最大为 w [ p ] ,该障碍物两端的编号为 L [ p ] , R [ p ] ,那么有转移

d p [ l ] [ r ] = m i n ( d p [ l ] [ r ] , d p [ l ] [ k 1 ] + d p [ k + 1 ] [ r ] + w [ p ] ) , L [ p ] k R [ p ]

时间复杂度 O ( n 3 )

Code

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 605
struct node
{
    int x,y;
    node(int _x=0,int _y=0)
    {
        x=_x,y=_y;
    }
    bool operator<(const node&b)const
    {
        return 1ll*x*b.y<1ll*y*b.x;
    }
    bool operator==(const node&b)const
    {
        return 1ll*x*b.y==1ll*y*b.x;
    }
}a[maxn];
int T,n,L[maxn],R[maxn],H[maxn],W[maxn];
ll dp[maxn][maxn];
ll dfs(int l,int r)
{
    if(l>=r)return 0;
    if(dp[l][r]!=1e18)return dp[l][r];
    int p=0;
    for(int i=1;i<=n;i++)
        if(L[i]>=l&&R[i]<=r)
            if(p==0||W[p]<W[i])p=i;
    if(p==0)return dp[l][r]=0;
    for(int k=L[p];k<=R[p];k++)
        dp[l][r]=min(dp[l][r],dfs(l,k-1)+dfs(k+1,r)+W[p]);
    return dp[l][r];
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int m=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&H[i],&L[i],&R[i],&W[i]);
            a[m++]=node(L[i],H[i]),a[m++]=node(R[i],H[i]);
        }
        sort(a,a+m);
        m=unique(a,a+m)-a;
        for(int i=1;i<=n;i++)
        {
            L[i]=lower_bound(a,a+m,node(L[i],H[i]))-a+1;
            R[i]=lower_bound(a,a+m,node(R[i],H[i]))-a+1;
        }
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
                dp[i][j]=1e18;
        printf("%lld\n",dfs(1,m));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/V5ZSQ/article/details/82562802