飞扬的小鸟 DP

飞扬的小鸟 DP

细节有点恶心的DP,设\(f[i][j]\)表示横坐标为\(i\)(从\(0\)开始)高度为\(j\)时,屏幕点击的最小次数为\(f[i][j]\),转移便很好写了,这里要注意枚举当前状态时要枚举完所有\(j\),因为每次转移只向上跳了一次,所以必须枚举完。

for(int j=1;j<=m+xd[i];++j)
	if(j-xd[i]>=0)
		f[i][j]=min(f[i][j-xd[i]]+1, f[i-1][j-xd[i]]+1); // 向上跳
for(int j=mih[i];j<=mxh[i];++j)
  f[i][j]=min(f[i][j], f[i-1][j+yd[i]]); // 向下落

但是题目还有高度限制,即如果跳到\(m\)以上,高度仍算\(m\),所以我们还要对于\(m\)以上转移一下

for(int j=m+1;j<=m+xd[i];++j)
	f[i][m]=min(f[i][m], f[i][j]);

然后还要处理一下非法状态,因为之前枚举了所有状态。

for(int j=1;j<=mih[i]-1;++j) f[i][j]=INF;
for(int j=mxh[i]+1;j<=m+xd[i];++j) f[i][j]=INF;

AC Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
#define MAXN 10010
using namespace std;
inline int read(){
    char ch=getchar();int s=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') s=s*10+(ch^'0'), ch=getchar();
    return s;
}
int mxh[MAXN],mih[MAXN];
int xd[MAXN],yd[MAXN];
int f[MAXN][2002];
bool hav[MAXN];
int n,m,k;
int main(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=n;++i) mxh[i]=m,mih[i]=1;
    for(int i=1;i<=n;++i) xd[i]=read(),yd[i]=read();
    for(int i=1;i<=k;++i){
        int p=read(),l=read(),h=read();
        hav[p]=1;
        mih[p]=l+1;
        mxh[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=1;j<=m+xd[i];++j)
            if(j-xd[i]>=0)
                f[i][j]=min(f[i][j-xd[i]]+1, f[i-1][j-xd[i]]+1);
        for(int j=m+1;j<=m+xd[i];++j)
            f[i][m]=min(f[i][m], f[i][j]);
        for(int j=mih[i];j<=mxh[i];++j)
            f[i][j]=min(f[i][j], f[i-1][j+yd[i]]);
        for(int j=1;j<=mih[i]-1;++j) f[i][j]=INF;
        for(int j=mxh[i]+1;j<=m+xd[i];++j) f[i][j]=INF;
        //for(int j=mih[i];j<=mxh[i];++j) printf("f[%d][%d]=%d\n", i, j, f[i][j]);
    }
    int ans=INF;
    for(int j=1;j<=m;++j)
        ans=min(ans, f[n][j]);
    if(ans<INF){
        printf("1\n%d", ans);
        return 0;
    }
    for(int i=n-1;i>=0;--i){
        int tmp=INF;
        for(int j=1;j<=m;++j)
            tmp=min(tmp, f[i][j]);
        if(tmp<INF){
            ans=i;
            break;
        }
    }
    int cnt=0;
    for(int i=0;i<=ans;++i)
        if(hav[i]) ++cnt;
    printf("0\n%d", cnt);
    return 0;
}
posted @ 2019-11-08 07:25  Santiego  阅读(111)  评论(0编辑  收藏  举报