NOIP2014Day1T3-飞扬的小鸟

版权声明:不念过去,不畏未来,一切都是过眼云烟。 https://blog.csdn.net/qq_34531807/article/details/83514695


题解:
f [ i ] [ j ] f[i][j] 表示横坐标为 i i 时高度为j的最少点击次数。
用正无穷来表示不可能达到这个状态。
于是我们可以分析出状态转移的方式:
上升——完全背包转移方式
下降—— 01 01 背包转移方式
超过 m m 变为 m m ——特判
C o d e Code:

#include<bits/stdc++.h>
#define ll long long
const int N=1e4+5;
using namespace std;
int n,m,k,vis[N],low[N],high[N],x[N],y[N],f[N][2005];
inline ll read()
{
    ll x=0,f=1;char s=getchar();
    while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
    while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
int main()
{
    n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++)
    {
        x[i]=read(),y[i]=read();
        high[i]=m;low[i]=1;
    }
    for(int i=1;i<=k;i++)
    {
        int p=read(),l=read(),h=read();
        vis[p]=1;low[p]=l+1;high[p]=h-1;
    }
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=m;i++)f[0][i]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=x[i]+1;j<=m+x[i];j++)
            f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);
        for(int j=m+1;j<=m+x[i];j++)f[i][m]=min(f[i][m],f[i][j]);
        for(int j=1;j<=m-y[i];j++)f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
        for(int j=1;j<low[i];j++)f[i][j]=f[0][0];
        for(int j=high[i]+1;j<=m;++j)f[i][j]=f[0][0];
    }
    int ans=f[0][0];
    for(int j=1;j<=m;j++)ans=min(ans,f[n][j]);
    if(ans<f[0][0])printf("1\n%d\n",ans);else
    {
        int i,j;
    	for(i=n;i>=1;i--)
        {
            for(j=1;j<=m;j++)
                if(f[i][j]<f[0][0])break;
            if(j<=m)break;
        }
        ans=0;
        for(int j=1;j<=i;j++)if(vis[j])ans++;
        printf("0\n%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/83514695