zoukankan      html  css  js  c++  java
  • NOIP2014 Day1

    T1水题:

    P1328 生活大爆炸版石头剪刀布

    #include<bits/stdc++.h>
    using namespace std;
    #define N 205
    #define ri register int
    int a[N],b[N];
    int check(int a,int b)
    {
        if(a==b) return 0;
        if(a==0){
            if(b==1 ||b==4) return 2;
            return 1;
        }
        if(a==1){
            if(b==2 || b==4) return 2;
            return 1;
        }
        if(a==2){
            if(b==0 || b==3) return 2;
            return 1;
        }
        if(a==3){
            if(b==0 || b==1) return 2;
            return 1;
        }
        if(a==4){
            if(b==3 || b==2) return 2;
            return 1;
        }
        return 0;
    }
    int main()
    {
        int n,n1,n2;
        scanf("%d%d%d",&n,&n1,&n2);
        for(ri i=1;i<=n1;++i) scanf("%d",&a[i]);
        for(ri i=1;i<=n2;++i) scanf("%d",&b[i]);
        int i=1,j=1,A=0,B=0;
        while(n--){
            if(i>n1) i=1;
            if(j>n2) j=1;
            
            int x=check(a[i],b[j]);
            //printf("a:%d b:%d x:%d
    ",a[i],b[j],x);
            if(x==1) A++;
            else if(x==2) B++;
            i++,j++;
        }
        printf("%d %d
    ",A,B);
    }
    /*
    10 5 6
    0 1 2 3 4
    0 3 4 2 1 0
    */
    View Code

    T2水题:

    P1351 联合权值

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 200005
    #define mod 10007
    #define ri register int
    ll ans=0,maxx=0,lmx[N],mx[N],sum[N],w[N];
    int tot=0,head[N],nex[N<<1],to[N<<1],fa[N];
    void add(int a,int b) { to[++tot]=b; nex[tot]=head[a]; head[a]=tot; }
    void dfs1(int u,int ff)
    {
        for(ri i=head[u];i;i=nex[i]){
            int v=to[i];
            if(v==ff) continue;
            sum[u]+=w[v]; //sum[u]%=mod; 注意sum不要取mod 否则会在下面减成负数!!! 
            if(!mx[u]) mx[u]=w[v];
            else if(w[v]>mx[u]) lmx[u]=mx[u],mx[u]=w[v];
            else if(w[v]>lmx[u]) lmx[u]=w[v];
            fa[v]=u;
            dfs1(v,u);
        }
    }
    void dfs2(int u,int ff)
    {
        for(ri i=head[u];i;i=nex[i]){
            int v=to[i];
            if(v==ff) continue;
            ans+=w[v]*(sum[u]-w[v]) %mod; ans%=mod;
            ans+=w[v]*w[ff] %mod *2 %mod; ans%=mod;
            maxx=max(maxx,w[v]*w[ff]);
            dfs2(v,u);
        }
        maxx=max(maxx,mx[u]*lmx[u]);
    }
    int main()
    {
        int n,a,b;
        scanf("%d",&n);
        for(ri i=1;i<=n-1;++i) scanf("%d%d",&a,&b),add(a,b),add(b,a);
        for(ri i=1;i<=n;++i) scanf("%lld",&w[i]);
        dfs1(1,0);
        dfs2(1,0);
        printf("%lld %lld
    ",maxx,ans%mod);
    }
    /*
    6
    1 2
    1 3
    1 4
    2 6
    2 5
    1 2 3 4 5 6
    */
    View Code

    T3简单dp:

    P1941 飞扬的小鸟

    分析:

    对于简单的模拟水题,应该看清楚题目要求和数据范围。

    对于有减法又有%的题,注意不要减成负数,要( ……+mod )%mod。

    T3的直接dp,复杂度大,只能得75分:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x7f7f7f
    #define N 10005
    #define M 1005
    #define ll long long
    #define ri register int
    int x[N],y[N];
    ll dp[N][M];
    struct node{
        int u,v,fl;
    }g[N];
    int main()
    {
        int n,m,k,a,b,c,fll=0,tmp;
        scanf("%d%d%d",&n,&m,&k);
        for(ri i=0;i<=n-1;++i) scanf("%d%d",&x[i],&y[i]);
        for(ri i=1;i<=k;++i) scanf("%d%d%d",&a,&b,&c),g[a].u=b,g[a].v=c,g[a].fl=1;
        for(ri i=0;i<=n;++i)
        if(!g[i].fl) g[i].u=0,g[i].v=m+1;
        for(ri i=0;i<=n;++i) for(ri j=0;j<=m;++j) dp[i][j]=inf;
        for(int i=g[0].u;i<=g[0].v;++i) dp[0][i]=0;
        for(ri i=0;i<=n-1;++i){//
            bool fl=0;
            for(ri j=g[i].u+1; j<=g[i].v-1 ; ++j){
                int pos= j-y[i] ;//上一次不点 这一次的高度
                if( pos<g[i+1].v && pos>g[i+1].u ) //可以通过这一个管道 
                dp[i+1][pos]=min(dp[i+1][pos] , dp[i][j]);
                int up=( g[i+1].v-j )/x[i] +1, down= ( g[i+1].u-j )/x[i];//上一次最多点的次数和最少点的次数 
                down=max(1,down);
                for(ri k=down;k<=up;++k){
                    pos=j+x[i]*k;//点k次后这一次的高度 
                    if( pos>0 && (!g[i+1].fl) && pos>m ) pos=m;
                    if( pos<g[i+1].v && pos>g[i+1].u ) 
                    dp[i+1][pos]=min(dp[i+1][pos] , dp[i][j]+k);
                }
            }
            for(ri j=g[i+1].u+1; j<=g[i+1].v-1; ++j) if(dp[i+1][j]!=inf) fl=1;
            if(!fl) { fll=1; tmp=i; break; }
        }
        if(fll){//统计最多到的水管数 
            ll ans=0;
            for(ri i=1;i<=tmp;++i) 
            ans+=g[i].fl;
            printf("0
    %lld
    ",ans);
            return 0;
        }
        ll ans=inf;
        for(ri i=g[n].u+1;i<=g[n].v-1;++i) ans=min(ans,dp[n][i]);
        printf("1
    %lld
    ",ans);
        return 0;
    }
    /*
    10 10 6 
    3 9  
    9 9  
    1 2  
    1 3  
    1 2  
    1 1  
    2 1  
    2 1  
    1 6  
    2 2  
    1 2 7 
    5 1 5 
    6 3 5 
    7 5 8 
    8 7 9 
    9 1 3 
    
    */
    简单dp 75

    正解是背包或者利用背包的思路进行优化:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x7f7f7f
    #define N 10005
    #define M 2005
    #define ll long long
    #define ri register int
    int x[N],y[N];
    ll dp[N][M];
    struct node{
        int u,v,fl;
    }g[N];
    int main()
    {
        int n,m,k,a,b,c,fll=0,tmp;
        scanf("%d%d%d",&n,&m,&k);
        for(ri i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);
        for(ri i=1;i<=k;++i) scanf("%d%d%d",&a,&b,&c),g[a].u=b,g[a].v=c,g[a].fl=1;
        for(ri i=0;i<=n;++i)
        if(!g[i].fl) g[i].u=0,g[i].v=m+1;
        for(ri i=0;i<=n;++i) for(ri j=0;j<=m+1;++j) dp[i][j]=inf;
        for(int i=g[0].u+1;i<=g[0].v-1;++i) dp[0][i]=0;
        for(ri i=1;i<=n;++i){
            for(ri j=x[i]+1;j<=m+x[i];++j)//上升是完全背包 
            dp[i][j]=min( dp[i-1][j-x[i]]+1 , dp[i][j-x[i]]+1 );
            
            for(ri j=m+1;j<=m+x[i];++j)//处理超过m的部分 
            dp[i][m]=min(dp[i][m],dp[i][j]);
            
            for(ri j=1;j<=m-y[i];++j)//下降是01背包 
            dp[i][j]=min(dp[i][j],dp[i-1][j+y[i]]);
            
            for(ri j=0;j<=g[i].u;++j) dp[i][j]=inf;//将不能到达的地方赋成inf 
            for(ri j=g[i].v;j<=m;++j) dp[i][j]=inf;
        }
        ll ans=inf; int fl=0;
        for(ri i=1;i<=m;++i) ans=min(ans,dp[n][i]);
        if(ans==inf){
            int pos;
            for(ri i=n;i>=0;--i){//倒着回去看 是哪个横坐标飞不过去了 
                for(ri j=1;j<=m;++j)
                if(dp[i][j]<inf) { fl=1; break ; }
                if(fl) { pos=i; break; }
            }
            ans=0;
            for(ri i=0;i<=pos;++i) ans+=g[i].fl;//统计水管数 
            printf("0
    %lld
    ",ans);
            return 0;
        }
        printf("1
    %lld
    ",ans);
        return 0;
    }
    /*
    10 10 6 
    3 9  
    9 9  
    1 2  
    1 3  
    1 2  
    1 1  
    2 1  
    2 1  
    1 6  
    2 2  
    1 2 7 
    5 1 5 
    6 3 5 
    7 5 8 
    8 7 9 
    9 1 3 
    
    */
    View Code

    总之,题虽简单,还是有很多细节要注意的。

  • 相关阅读:
    送给热爱书法的朋友们
    [原创]中秋随笔 祝大家中秋快乐
    Comsenz力邀您的加盟
    夜半冻醒有感
    Comsenz力邀您的加盟
    成熟的谷子先低头
    [转载]10个经典的web2.0配色方案网站
    无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”
    C#获取真实IP地址及分析
    使用TRY CATCH进行SQL Server异常处理
  • 原文地址:https://www.cnblogs.com/mowanying/p/11529132.html
Copyright © 2011-2022 走看看