【noip2014】tyvj 4056飞扬的小鸟

来源:互联网 发布:乐知英语的公司在哪 编辑:程序博客网 时间:2024/04/25 08:37

2个小时10分钟【中间玩了会?】 写完+调完+改完。

感觉 dp真 tm难写

打算认真 写个 结题报告。qaq

看了这道题 很多遍了。。

说实话 一点思路也没有。考场上 估计 瞎写写 得个10分 就 很高了。。。

然后坐在 我旁边的 哀家 搜结题报告的时候 说 是 dp

这才 开始想。。。。。

这么一想 感觉很有道理吗!

暂时 不考虑 管子 们 只考虑 当前位置 多少次能到达

那 这不是完全背包吗!诶?可是我不想 再枚举 几个高度 啊?

不怕,这个可以 用 dp[i][]和dp[i-1][]来更新啊!为什么 ?dp[i-1]很好理解吧。那dp[i][j-x[i-1]]就是 由 dp[i-1][j-2*x[i-1]]+1再+1搞定啊!

所以 这就不怕了吧!

然后就是一些 tube和细节的处理
1.在到达高度为m的时候 不光可以 由m-x[i-1]更新,还可以由>m-x[i-1]的
2.处理下降
3.处理tube

还有要 看清题:
一开始 第二组样例一直过不了,就是 一直以为 是能到多远,人家问的是 过几根管。。。。

上代码:

#include<cstdio>#include<algorithm>#include<cstring>#define inf 0x3fffffffusing namespace std;//by mars_chint n,m,k;int up[10005],down[10005];//up是上沿 int x[10005],y[10005];int vis[10005];int dp[10005][1005];int main(){    scanf("%d%d%d",&n,&m,&k);    for(int i=0;i<n;i++)    {        scanf("%d%d",&x[i],&y[i]);    }    for(int i=1;i<=n;i++)    {        down[i]=0;        up[i]=m+1;    }    for(int i=1;i<=k;i++)    {        int p,a,b;        scanf("%d%d%d",&p,&a,&b);        up[p]=b,down[p]=a;        vis[p]=1;    }     for(int i=0;i<=n;i++)    {        for(int j=0;j<=m;j++)        {            dp[i][j]=inf;        }    }    for(int i=1;i<=m;i++)    {        dp[0][i]=0;    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            if(j>=x[i-1])            {                dp[i][j]=min(min(dp[i][j],dp[i-1][j-x[i-1]]+1),dp[i][j-x[i-1]]+1);            }            if(j == m)            {                for(int k=j-x[i-1];k<=m;k++)                {                    dp[i][j]=min(dp[i][j],min(dp[i-1][k]+1,dp[i][k]+1));                }            }        }        for(int j=1;j<=m;j++)        {            if(j+y[i-1]<=m)            {                dp[i][j]=min(dp[i][j],dp[i-1][j+y[i-1]]);            }        }        for(int j=1;j<=down[i];j++) dp[i][j]=inf;        for(int j=up[i];j<=m;j++) dp[i][j]=inf;    }    int ans=inf;    for(int i=1;i<=m;i++)    {        ans=min(ans,dp[n][i]);    }    bool flag=false;    int pos=0,cnt=0;    if(ans == inf)    {        printf("0\n");        for(int i=n-1;i>=1;i--)        {            for(int j=1;j<=m;j++)            {                if(dp[i][j]!=inf)                {                    pos=i;                    flag=true;                    break;                }            }            if(flag) break;        }        for(int j=1;j<=pos;j++)        {            if(vis[j]) cnt++;        }        printf("%d\n",cnt);    }    else printf("1\n%d\n",ans);}
0 0
原创粉丝点击