NOIP 2014 Day1 T3飞扬的小鸟

题目描述:http://codevs.cn/problem/3729/
表示各种shabi的我编和调了半天,思路大体就是一个完全背包的模型,不过会多一些额外的转移(因为题目限制高度之类的),不过值得注意的是应该先向上转移一遍再向下,不然会WA
——————————分割线—————————–

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define DAN 999999999//被假定为最大值 
int f[10010][10010]={0};
int up[10010]={0},down[10010]={0};//每个位置点击1次上升的高度和不点击下降的高度 
int maxhigh[10010]={0},minhigh[10010]={0};//上界 和 下界(有管子的就是上、下管子,无管子就是m+1,0) 
int n,m,k;
int step=0;//可以通过的管子数目 
int minstep=DAN;//最少点击数 

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i=0;i<n;i++)
        scanf("%d%d",&up[i],&down[i]);
    for (int i=0;i<=n;i++)
        {
            maxhigh[i]=m+1;
            minhigh[i]=0;
        }//初始化上、下界 
    int x;
    for (int i=1;i<=k;i++)
        {
            scanf("%d",&x);
            scanf("%d%d",&minhigh[x],&maxhigh[x]);
        }
    for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
                {
                    f[i][j]=DAN;
                    if (j-up[i-1]>0)
                        f[i][j]=min(f[i][j],min(f[i-1][j-up[i-1]],f[i][j-up[i-1]])+1);
                }//完全背包部分 
            for (int j=m-up[i-1]; j<=m; j++)
                f[i][m]=min(f[i][m],min(f[i][j],f[i-1][j])+1);//到顶的问题 
            for (int j=minhigh[i]+1; j<=maxhigh[i]-1; j++)
                if (j+down[i-1]<=m)
                    f[i][j]=min(f[i][j],f[i-1][j+down[i-1]]);
            for (int j=1; j<=minhigh[i]; j++)
                f[i][j]=DAN;//在最后一层(即落地,或下管子)都不可以 
            for (int j=maxhigh[i]; j<=m; j++)
                f[i][j]=DAN;//上管子到顶部不可以 
            bool pd=false;
            for (int j=1; j<=m; j++)
                if (f[i][j]<DAN)
                    pd=true;//判断在这个位置是否能够过关 
            if (!pd) 
                {
                    printf("0\n");
                    printf("%d",step);
                    return 0;
                }//如果不能过关就输出过了几根管子 
            else 
                if (maxhigh[i]!=m+1)
                    step++;//如果经过的是管子,经过管子数+1 
        }
    for (int i=1; i<=m; i++)
            minstep=min(minstep,f[n][i]);//从到达终点的各种方案中选择点击数最少的 
    printf("1\n");
    printf("%d",minstep);
  return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值