• noip2014 飞扬的小鸟


    这题之前做过…先听后做的 所以直接打了优化的dp、
    然而不是自己想的方法还是理解的不好 一直75分 wa到挺
    今天考试看到暴力dp70分 很自信加上点 continue break啥的就80+了
    比优化的dp得分多 机智的我哈哈哈…..
    然而手残了..枚举k次蹦跶结果转移的时候我特么都是+1不是+k
    悲伤的我眼泪掉下来…..
    然后改过来就80了 又不好办了..
    下面是80分代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 10010
    using namespace std;
    int n,m,K,f[maxn][maxn/10],ans=0x7fffffff,s;
    int Xi[maxn],Sh[maxn],X[maxn],Y[maxn],falg[maxn];//X 为上 Y为下 
    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++)
          Xi[i]=0,Sh[i]=m+1;
        int x,y,z;
        for(int i=1;i<=K;i++)
          {
              scanf("%d%d%d",&x,&y,&z);
              Xi[x]=y;Sh[x]=z;falg[x]=1;
          }
        memset(f,127/3,sizeof(f));
        for(int i=1;i<=m;i++)f[0][i]=0;
        for(int i=0;i<n;i++)
          for(int j=1;j<=m;j++)
            {
              if(f[i][j]==f[0][0])continue;
              int ii,jj,li=m/X[i]+1;
              for(int k=1;k<=li;k++)
                {
                  ii=i+1,jj=j+k*X[i];if(jj>m)jj=m;
                  if(jj<=Xi[ii]||jj>=Sh[ii])continue;
                  f[ii][jj]=min(f[ii][jj],f[i][j]+k);
                }
              ii=i+1;jj=j-Y[i];
              if(jj<=Xi[ii]||jj>=Sh[ii])continue;
              f[ii][jj]=min(f[ii][jj],f[i][j]);
            }
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            if(f[i][j]<f[0][0]&&falg[i]==1)
              {
                  s++;break;
              }
        for(int i=1;i<=m;i++)
          ans=min(ans,f[n][i]);
        if(s==K)printf("1
    %d
    ",ans);
        else printf("0
    %d
    ",s);
        return 0;
    }
     
    后来同桌终于在提交40+遍之后找到了错误
    真是 隐蔽….
    果然不是自己想的方法不好差错误啊…
    这里的优化是省掉了枚举蹦跶几次 那蹦跶好几次的怎么办呢
    可以认为他是先蹦跶到i,j 的下面I,j-h的地方然后在一次到I j
    图自己脑补一下. 注意先处理上升在处理下落 要不可能上升时用到的状态的刚才下落来的.
    下面是wa到挺得75分
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define inf 10000
    #define maxn 10010
    using namespace std;
    int n,m,k,up[maxn],down[maxn],ans=inf,now;
    int lu[maxn],ld[maxn],f[maxn][maxn/10],far;
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
          {
              scanf("%d%d",&up[i],&down[i]);
              lu[i]=m+1;ld[i]=0;
          }
        int x,y,z;
        for(int i=1;i<=k;i++)
          {
              scanf("%d%d%d",&x,&y,&z);
              ld[x]=y;lu[x]=z;
          }
        memset(f,127/3,sizeof(f));
        for(int i=0;i<=m;i++)f[0][i]=0;
        for(int i=1;i<=n;i++)
          {
              if(ld[i]!=0||lu[i]!=m+1)now++;
              for(int j=1;j<=m;j++)
                {
                    int ji=j+up[i];if(ji>m)ji=m;
                    if(ji<=ld[i]||ji>=lu[i])continue;
                    f[i][ji]=min(f[i][ji],f[i-1][j]+1);
                    f[i][ji]=min(f[i][ji],f[i][j]+1);
                if(i==n)ans=min(ans,f[i][ji]);
                if(f[i][ji]<inf)far=now;
              }
            for(int j=1;j<=m;j++)
              {
                  int ji=j-down[i];
                  if(ji<=ld[i]||ji>=lu[i])continue;
                  f[i][ji]=min(f[i][ji],f[i-1][j]);
                  if(i==n)ans=min(ans,f[i][ji]);
                  if(f[i][ji]<inf)far=now;
              }
          }
        for(int i=1;i<=m;i++)
          ans=min(ans,f[n][i]);
        if(far==k)printf("1
    %d
    ",ans);
        else printf("0
    %d
    ",far);
        return 0;
    }
    错误出在那两个continue上…
    可能出现那种省略掉k的转移正好来自柱子上 但是他是我们脑补出来的 他是合法的状态
    所以不能continue掉 应该先更新完 再给柱子弄成inf
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 10010
    #define inf 707406378
    using namespace std;
    int n,m,k,up[maxn],down[maxn],ans=0x7fffffff,now;
    int lu[maxn],ld[maxn],f[maxn][maxn/10],far,falg[maxn];
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<n;i++)
          {
              scanf("%d%d",&up[i],&down[i]);
              lu[i]=m+1;ld[i]=0;
          }
        ld[n]=0;lu[n]=m+1;
        int x,y,z;
        for(int i=1;i<=k;i++)
          {
              scanf("%d%d%d",&x,&y,&z);
              ld[x]=y;lu[x]=z;falg[x]=1;
          }
        memset(f,127/3,sizeof(f));
        for(int i=0;i<=m;i++)f[0][i]=0;
        for(int i=0;i<n;i++)
          {
              for(int j=1;j<=m;j++)
                {
                    int ji=j+up[i],ii=i+1;if(ji>m)ji=m;
                    f[ii][ji]=min(f[ii][ji],f[i][j]+1);
                    f[ii][ji]=min(f[ii][ji],f[ii][j]+1);
              }
            for(int j=1;j<=m;j++)
              if(j<=ld[i+1]||j>=lu[i+1])f[i+1][j]=inf;
            for(int j=1;j<=m;j++)
              {
                  int ji=j-down[i],ii=i+1;
                  if(ji<=ld[ii]||ji>=lu[ii])continue;
                  f[ii][ji]=min(f[ii][ji],f[i][j]);
              }
          }
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            if(f[i][j]<inf&&falg[i]==1)
              {
                  far++;break;
              }
        for(int i=1;i<=m;i++)
          ans=min(ans,f[n][i]);
        if(far==k)printf("1
    %d
    ",ans);
        else printf("0
    %d
    ",far);
        return 0;
    }
  • 相关阅读:
    Diocp截图
    [DIOCP视频]-DIOCPFileServer视频
    DIOCP 运作核心探密
    DIOCP-DIOCPv5的处理能力
    【被C折腾系列】用C调DIOCP编码客户端通信
    DIOCP-V5发布
    MyBean通用报表插件介绍
    Amazon
    输出所有大小写字符的组合
    删除最少字符生成Palindrome
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5781704.html
Copyright © 2020-2023  润新知