【洛谷】 P1941 飞扬的小鸟 (题解)

题目链接

这题关于DP

用f[i][j]表示横坐标为i时高度为j的最少点击次数。

用正无穷来表示不可能达到这个状态。

于是我们可以分析出状态转移的方式:

上升——完全背包转移方式

下降——01背包转移方式

超过m变为m——特判

细节详见代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int maxx=100000;
int l[10010],h[10010];
int f[10010][1010];
int x[10010],y[10010];
bool p[10010];
int main()
{
    int n,i,j,k,m,w;
    cin>>n>>m>>k;
    for(i=0;i<n;i++)
    {
        cin>>x[i]>>y[i];
        l[i]=0;
        h[i]=m+1;
    }
    l[n]=0;
    h[n]=m+1;
    for(i=0;i<k;i++)
    {
        cin>>w;
        cin>>l[w]>>h[w];
        p[w]=true;
    }
    for(i=1;i<=n;i++)
    {
        for(j=0;j<=m;j++)
        {
            f[i][j]=maxx;
        }
    }
    f[0][0]=maxx;
    for(i=1;i<=m;i++)
    {
        f[0][i]=0;
    }
    for(i=1;i<=n;i++)
    {
        for(j=x[i-1];j<=m;j++)
        {
            if(j==m)
            {
                for(w=m-x[i-1];w<=m;w++)
                {
                    f[i][j]=min(f[i][j],f[i-1][w]+1);
                    f[i][j]=min(f[i][j],f[i][w]+1);
                }
            }
            f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1);
            f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1);
        }
        for(j=max(1,l[i]+1);j<=min(m-y[i-1],h[i]-1);j++)
        {
            f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
        }
        for(j=l[i];j>=1;j--)
        {
            f[i][j]=maxx;
        }
        for(j=h[i];j<=m;j++)
        {
            f[i][j]=maxx;
        }
    }
    int ans=maxx;
    int cnt=k;
    for(i=n;i>=1;i--)
    {
        for(j=l[i]+1;j<=h[i]-1;j++)
        {
            ans=min(ans,f[i][j]);
        }
        if(ans<maxx)
        {
            break;
        }
        if(p[i]==true)
        {
            k--;
        }    
    }
    if(cnt==k)
    {
        cout<<"1"<<endl<<ans;
    }
    else
    {
        cout<<"0"<<endl<<k;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BorisDimitri/p/13546616.html