UVALive 6042 Bee Tower (dp)

来源:互联网 发布:程序员找工作保密协议 编辑:程序博客网 时间:2024/06/18 01:05

题目:传送门

思路:题目要求能从地面开始跳到最高的塔,在满足这个条件的前提下移动塔,并求出移动塔的最小花费。那么先找到最高的塔,然后向左右两边遍历,看看是否能到达地面,然后用dp求解最小移动花费。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<queue>#include<map>#include<stack> #include<vector>#include<algorithm>#define N 55#define INF 10000000#define LL long long#define EPS 1e-8using namespace std;struct tower{    int p,h;}tow[N];int n,W,H;int dp[N][605];int cmp(tower a,tower b){    return a.p<b.p;}int main(){    int T;    int maxh;    scanf("%d",&T);    for(int t=1;t<=T;t++)    {        scanf("%d%d%d",&n,&H,&W);        maxh=0;        for(int i=1;i<=n;i++)        {            scanf("%d%d",&tow[i].p,&tow[i].h);            maxh=max(maxh,tow[i].h);        }        int l,r;        bool flag;        int ans=INF;        for(int i=1;i<=n;i++)        {            if(maxh<=H)            {                ans=0;                break;            }            if(tow[i].h!=maxh) continue;            l=i-1;            flag=true;            while(l>0)            {                if(tow[l+1].h-tow[l].h>H)                {                    flag=false;                    break;                }                if(tow[l].h<=H) break;                l--;            }            //cout<<l<<endl;            if(flag&&l>0)            {                memset(dp,0,sizeof(dp));                for(int j=1;i-j>=l;j++)                {                    for(int p=tow[i].p-j;p>=max(0,tow[i].p-W*j);p--)                    {                        int minw=INF;                        for(int pl=max(p+1,tow[i].p-W*(j-1));pl<=min(p+W,tow[i].p-j+1);pl++)                        {                            minw=min(minw,dp[j-1][pl]);                        }                        dp[j][p]=abs(tow[i-j].p-p)*tow[i-j].h+minw;                        if(i-j==l) ans=min(dp[j][p],ans);                    }                }            }            r=i+1;            flag=true;            while(r<=n)            {                if(tow[r-1].h-tow[r].h>H)                {                    flag=false;                    break;                }                if(tow[r].h<=H) break;                r++;            }            if(flag&&r<=n)            {                memset(dp,0,sizeof(dp));                for(int j=1;j+i<=r;j++)                {                    for(int p=tow[i].p+j;p<=tow[i].p+W*j;p++)                    {                        int minw=INF;                        for(int pl=min(p-1,tow[i].p+W*(j-1));pl>=max(p-W,tow[i].p+j-1);pl--)                        {                            minw=min(minw,dp[j-1][pl]);                        }                        dp[j][p]=abs(tow[i+j].p-p)*tow[i+j].h+minw;                        if(j+i==r) ans=min(ans,dp[j][p]);                    }                }            }        }        if(ans==INF) ans=-1;        printf("Case #%d: %d\n",t,ans);    }}