【NOIP2014】飞扬的小鸟

来源:互联网 发布:sql统计两个字段总和 编辑:程序博客网 时间:2024/05/01 09:23

【codevs 3729】
3729 飞扬的小鸟
时间限制: 1 s 空间限制: 128000 KB
题目描述 Description
这里写图片描述
输入描述 Input Description
这里写图片描述

输出描述 Output Description
输出文件名为 bird.out。
共两行。
第一行,包含一个整数,如果可以成功完成游戏,则输出 1,否则输出 0。
第二行,包含一个整数,如果第一行为 1,则输出成功完成游戏需要最少点击屏幕数,否则,输出小鸟最多可以通过多少个管道缝隙。

样例
这里写图片描述
这里写图片描述
【输入输出样例说明】
如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。
这里写图片描述

数据范围及提示 Data Size & Hint
对于 30%的数据:5≤n≤10,5≤m≤10,k=0,保证存在一组最优解使得同一单位时间最多点击屏幕 3 次;
对于 50%的数据:5≤n≤20,5≤m≤10,保证存在一组最优解使得同一单位时间最多点击屏幕 3 次;

对于 70%的数据:5≤n≤1000,5≤m≤100;
对于 100%的数据: 5≤n≤10000, 5≤m≤1000,0≤k

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 10005;int n,m,k,sp,sl,sh,summer,xczhw;int dp[10005][1005],cnt;int up[MAXN],down[MAXN];int l[MAXN],h[MAXN];/*          加特技的背包问题 */int main(){    memset(dp,0x7f,sizeof(dp));    memset(up,0,sizeof(up));    memset(down,0,sizeof(down));    memset(l,0,sizeof(l));    memset(h,0,sizeof(h));    scanf("%d %d %d",&n,&m,&k);    for(int i = 0; i < n; i ++)        scanf("%d %d",&up[i],&down[i]);    for(int i = 1;i <= n;i ++)//……     {        l[i] = 0;        h[i] = m + 1;    }       for(int i = 1; i <= k; i ++)    {        scanf("%d %d %d",&sp,&sl,&sh);        l[sp] = sl;        h[sp] = sh;    }    cnt = dp[0][0],xczhw = 0,summer = cnt;    for(int i = 1; i <= m; i ++)//从任意高度开始         dp[0][i] = 0;    for(int i = 1; i <= n; i ++)    {        summer = cnt;        for(int j = up[i - 1] + 1; j <= m; j ++)//最低是要点一次的 然后这是纵坐标了QAQ         {            if(j == m)//到最高的时候要注意QAQ                 for(int k = m - up[i - 1]; k <= m; k ++)                    dp[i][j] = min(dp[i][j],min(dp[i][k] + 1,dp[i - 1][k] + 1));            else//                dp[i][j] = min(dp[i][j],min(dp[i][j - up[i - 1]] + 1,dp[i - 1][j - up[i - 1]] + 1));        }        //处理管道          for(int j = 0; j <= l[i]; j ++)            dp[i][j] = cnt;        for(int j = h[i]; j <= m; j ++)            dp[i][j] = cnt;        //剩下的能走的部分QAQ        for(int j = l[i] + 1; j <= h[i] - 1; j ++)        {            if(j + down[i - 1] <= m)                dp[i][j] = min(dp[i][j],dp[i - 1][j + down[i - 1]]);            if(dp[i][j] < cnt)      summer = 0;        }        if(summer == cnt)        {            puts("0");            printf("%d\n",xczhw);            return 0;        }        if(h[i] != m + 1)            xczhw ++;           }    xczhw = cnt;    for(int i = l[n] + 1; i < h[i]; i ++ )//最右 !!!        if(dp[n][i] < xczhw)            xczhw = dp[n][i];    puts("1");    printf("%d\n",xczhw);    return 0;}
0 0
原创粉丝点击