zoukankan      html  css  js  c++  java
  • 【NOIP2014】Day1题解+代码

    Day1 T1

    签到题,模拟一下随便写就能过。

    不过小心像我一样表打错傻逼的调了10min。

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    int La=0,Lb=0,N=0;
    int xl_a[205]={0},xl_b[205]={0};
    int check[5][5]={{0,-1,1,1,-1},{1,0,-1,1,-1},{-1,1,0,-1,1},{-1,-1,1,0,1},{1,1,-1,-1,0}};
    int main(void)
    {
        freopen("rps.in","r",stdin);
        freopen("rps.out","w",stdout);
        scanf("%d%d%d",&N,&La,&Lb);
        for(int i=1;i<=La;i++)scanf("%d",&xl_a[i]);
        for(int i=1;i<=Lb;i++)scanf("%d",&xl_b[i]);
        int a=0,b=0,ans_a=0,ans_b=0;
        for(int i=1;i<=N;i++)
        {
            a=xl_a[i%La];
            if(!(i%La))a=xl_a[La];
            b=xl_b[i%Lb];
            if(!(i%Lb))b=xl_b[Lb];
            if(check[a][b]==1){ans_a++;continue;}
            if(check[a][b]!=0){ans_b++;;continue;}
        }
        printf("%d %d",ans_a,ans_b);
        return 0;
    }
    View Code

    T2

    没什么难度……不知道为什么能卡当时的我只拿70分。

    大概是不知道n个点n-1条边就是树?

    最开始写代码的时候没考虑兄弟节点的情况……后面紧急补上去了,还好发现了不然岂不是又得炸。

    一涉及到取模我的代码风格就变得乱七八糟。

    简述一下,我们对这棵树从1开始dfs,每到一个节点,就先更新答案(和它父亲的父亲)。

    然后枚举它的儿子节点,记录两个参数,max_son和tot,max_son是它儿子节点中权值最大的那个,tot是它所有儿子的权值和。

    max_son是更新第一个最大值的答案的,tot是更新第二个答案的。

    顺便提醒一下,因为题面上说的是有序点对,所以说我们每次更新第二个答案的时候都要记住乘个2……【血泪教训】

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    struct lb
    {
        int nw;
        int nxt;
    };
    lb line[400003];
    int n=0,cnt=0,val[200003]={0},head[200003]={0};
    int fa[200003]={0},ans1=0,ans2=0;
    void add(int f,int t);
    void dfs(int nw);
    int main(void)
    {
        freopen("link.in","r",stdin);
        freopen("link.out","w",stdout);
        scanf("%d",&n);
        int a=0,b=0;
        for(int i=1;i<=n-1;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=1;i<=n;i++)scanf("%d",&val[i]);
        fa[1]=0;
        dfs(1);
        printf("%d %d",ans1,ans2);
        return 0;
    }
    
    void add(int f,int t)
    {
        line[++cnt].nw=t;
        line[cnt].nxt=head[f];
        head[f]=cnt;
        return;
    }
    
    void dfs(int nw)
    {
        if(nw>n)return;
        if(fa[fa[nw]])
        {
            ans1=max(ans1,val[nw]*val[fa[fa[nw]]]);
            ans2+=val[nw]*val[fa[fa[nw]]]*2;
            ans2%=10007;
        }
        int next=0,max_son=0,tot=0;
        for(int i=head[nw];i>0;i=line[i].nxt)
        {
            next=line[i].nw;
            if(next==fa[nw])continue;
            ans1=max(ans1,val[next]*max_son);
            ans2+=(tot%10007)*val[next]*2;
            ans2%=10007;
            max_son=max(max_son,val[next]);
            tot+=val[next];
            tot%=10007;
            fa[next]=nw;
            dfs(next);
        }
        return;
    }
    View Code

     T3

    我和昨年一样没有长进【不还是多得了五分的】

    剩下的都是TLE。

    代码风格无论怎么说还是变了一些的。

    这题就是个背包,完全=A=,但是我写得丑写不过……

    昨年代码↓

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    using namespace std;
    ifstream fin("bird.in");
    ofstream fout("bird.out");
    bool jz[10002][1002]={0};//0表示可通行,1表示有管道 
    int ss[2][10002]={0};//0表示点击后上升,1表示向下坠落
    int DP[10002][1002]={0};//DP[i][j]表示在x坐标为i,y坐标为j下最小点击数 
    bool gd[10002]={0};//记录每一x坐标是否有管道 
    int Lx=0,Ly=0,Gds=0;
    int main(void)
    {
     fin>>Lx>>Ly>>Gds;
     for(int i=0;i<Lx;i++)fin>>ss[0][i]>>ss[1][i];
     int Gx=0,Up=0,Down=0;
     for(int i=1;i<=Gds;i++)
        {
         fin>>Gx>>Down>>Up;
         for(int j=0;j<=Down;j++)jz[Gx][j]=true;
         for(int j=Ly;j>=Up;j--)jz[Gx][j]=true;
         gd[Gx]=true;
        }
     memset(DP,127/2,sizeof(DP));
     for(int i=1;i<=Ly;i++)DP[0][i]=0;
     int ans=0x7fffffff,tgs=0,nxt=0;
     bool pd=false;
     for(int i=0;i<=Lx;i++)
        {
         ans=0x7fffffff;
         pd=false;
         for(int j=1;j<=Ly;j++)
            {
             if(DP[i][j]==1061109567)continue;
             if(jz[i][j])continue;
             pd=true;
             if(!jz[i+1][j-ss[1][i]]&&j-ss[1][i]>0)//如果不点击下一回合也不会死亡 
               {
                DP[i+1][j-ss[1][i]]=min(DP[i+1][j-ss[1][i]],DP[i][j]);
                if(DP[i+1][j-ss[1][i]]<ans)ans=DP[i+1][j-ss[1][i]];
               }
             for(int k=1;k<=Ly;k++)
                {
                 nxt=k*ss[0][i];//点击k次后下一次上升的位置 
                 if(nxt+j>Ly)nxt=Ly-j;
                 if(jz[i+1][j+nxt])continue;
                 DP[i+1][j+nxt]=min(DP[i+1][j+nxt],DP[i][j]+k);
                 if(DP[i+1][j+nxt]<ans)ans=DP[i+1][j+nxt];
                 if(nxt==Ly-j)break;
                }
            }
         if(!pd)break;
         if(gd[i])tgs++;
        }
     if(tgs==Gds)fout<<"1
    "<<ans;
     else fout<<"0
    "<<tgs;
     return 0;
    }
    View Code

    今年的↓

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n=0,m=0,k=0,bef[10005]={0};
    int up[10005]={0},down[10005]={0},dp[2][1005]={0};
    bool check[10005][1003]={0};
    const int INF=2139062143;
    int main(void)
    {
        freopen("bird.in","r",stdin);
        freopen("bird.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)scanf("%d%d",&up[i],&down[i]);
        int a=0,b=0,c=0;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            for(int j=0;j<=b;j++)check[a+1][j]=1;
            for(int j=c;j<=m;j++)check[a+1][j]=1;
            bef[a+1]++;
        }
        for(int i=1;i<=n;i++)bef[i]+=bef[i-1];
        memset(dp,0x7f,sizeof(dp));
        for(int i=1;i<=m;i++)dp[1][i]=0;
        int u=0,d=0,mark=0,ans=INF,loop=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(dp[i&1][j]!=INF&&!check[i][j])
                {
                    mark=i;
                    loop=max((m-j)/up[i]+1,1);
                    for(int k=1;k<=loop;k++)
                    {
                        u=min(m,j+up[i]*k);
                        if(!check[i+1][u])dp[(i+1)&1][u]=min(dp[(i+1)&1][u],dp[i&1][j]+k);
                        if(i==n)ans=min(ans,dp[(i+1)&1][u]);
                    }
                    d=max(0,j-down[i]);
                    if(d==0)continue;
                    if(!check[i+1][d])dp[(i+1)&1][d]=min(dp[(i+1)&1][d],dp[i&1][j]);
                    if(i==n)ans=min(ans,dp[(i+1)&1][d]);
                }
            }
            for(int j=1;j<=m;j++)dp[i&1][j]=INF;
        }
        if(mark<n)
        {
            printf("0
    %d",bef[mark]);
            return 0;
        }
        printf("1
    %d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    面向对象的-作用域
    什么时候会有作用域的形成
    面向对象-作用域
    1.3tableView向左滑动出现多个按钮操作
    tableView自带删除与添加操作
    使用偏好设置归档放到哪里
    使用RSA对数据进行加密
    12.22UIAlertController 使用
    在PCH中定制自己的LOG打印日志,分别在DEBUG 与 RELEASE的状态下处理,及如何把PCH引入到项目中
    在程序document文件夹里边创建新的文件夹及删除文件夹
  • 原文地址:https://www.cnblogs.com/CYWer/p/6043606.html
Copyright © 2011-2022 走看看