zoukankan      html  css  js  c++  java
  • 6.28集训--集训模拟赛2

    总结


    第一题:n只有4,直接暴力
    第二题:Tarjan缩点之后跑一个最长路
    第三题:DP
    第四题:思维量较大

    A、翻转游戏

    题目描述


    分析

    (n)的范围很小,所以我们考虑状压DP
    我们设(f[i][j][k][m])为第一行的状态为(i),第二行的状态为(j),第三行的状态为(k),第四题的状态为(m)所需要的最小步数
    所以我们暴力枚举6重循环,时间复杂度为(15 imes 15 imes 15 imes 15 imes 4 imes 4)

    考场95分代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5;
    int f[1<<maxn][1<<maxn][1<<maxn][1<<maxn];
    int zt[maxn];
    int main(){
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=4;i++){
            char s[10];
            scanf("%s",s);
            for(int j=0;j<4;j++){
                if(s[j]=='b'){
                    zt[i]+=(1<<j);
                }
            }
        }
        f[zt[1]][zt[2]][zt[3]][zt[4]]=0;
        for(int i=0;i<(1<<4);i++){
            for(int j=0;j<(1<<4);j++){
                for(int k=0;k<(1<<4);k++){
                    for(int m=0;m<(1<<4);m++){
                        for(int d=1;d<=4;d++){
                            if(d==1){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==2){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==3){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else {
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    }
                                }
                            } else {
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else {
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        int ans=min(f[0][0][0][0],f[15][15][15][15]);
        if(ans==0x3f3f3f3f) printf("Impossible
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    

    100分代码

    因为我们的状态不是从0开始的,所以我们不能只从状态为0正着开始枚举
    比如下面这一组数据

    bbbb
    bwwb
    bwwb
    bbbb
    

    正解应该输出4,但是上面的代码却输出6
    解决这一个问题,我们倒着枚举一遍就可以了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5;
    int f[1<<maxn][1<<maxn][1<<maxn][1<<maxn];
    int zt[maxn];
    int main(){
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=4;i++){
            char s[10];
            scanf("%s",s);
            for(int j=0;j<4;j++){
                if(s[j]=='b'){
                    zt[i]+=(1<<j);
                }
            }
        }
        f[zt[1]][zt[2]][zt[3]][zt[4]]=0;
        for(int i=0;i<(1<<4);i++){
            for(int j=0;j<(1<<4);j++){
                for(int k=0;k<(1<<4);k++){
                    for(int m=0;m<(1<<4);m++){
                        for(int d=1;d<=4;d++){
                            if(d==1){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==2){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==3){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else {
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    }
                                }
                            } else {
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else {
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        for(int i=(1<<4)-1;i>=0;i--){
            for(int j=(1<<4)-1;j>=0;j--){
                for(int k=(1<<4)-1;k>=0;k--){
                    for(int m=(1<<4)-1;m>=0;m--){
                        for(int d=1;d<=4;d++){
                            if(d==1){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=i^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[now][j^(1<<(n-1))][k][m]=min(f[now][j^(1<<(n-1))][k][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==2){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    } else {
                                        int now=j^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i^(1<<(n-1))][now][k^(1<<(n-1))][m]=min(f[i^(1<<(n-1))][now][k^(1<<(n-1))][m],f[i][j][k][m]+1);
                                    }
                                }
                            } else if(d==3){
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    } else {
                                        int now=k^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j^(1<<(n-1))][now][m^(1<<(n-1))]=min(f[i][j^(1<<(n-1))][now][m^(1<<(n-1))],f[i][j][k][m]+1);
                                    }
                                }
                            } else {
                                for(int n=1;n<=4;n++){
                                    if(n==1){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else if(n==2 || n==3){
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<n);
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    } else {
                                        int now=m^(1<<(n-1));
                                        now=now^(1<<(n-2));
                                        f[i][j][k^(1<<(n-1))][now]=min(f[i][j][k^(1<<(n-1))][now],f[i][j][k][m]+1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        int ans=min(f[0][0][0][0],f[15][15][15][15]);
        if(ans==0x3f3f3f3f) printf("Impossible
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    

    B、抢掠计划

    题目描述




    分析

    显然,处于同一个强连通分量的点可以互相到达
    所以我们将每一个强连通分量分别缩点
    缩完点后的图就变成了一个有向无环图
    这时,我们就可以用SPFA求出最长路

    100分代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6+5;
    int head[maxn],tot=1;
    struct asd{
        int from,to,next;
        ll val;
    }b[maxn],b2[maxn];
    void ad(int aa,int bb,ll cc){
        b[tot].from=aa;
        b[tot].to=bb;
        b[tot].next=head[aa];
        b[tot].val=cc;
        head[aa]=tot++;
    }
    int h2[maxn],t2=1;
    void ad2(int aa,int bb){
        b2[t2].from=aa;
        b2[t2].to=bb;
        b2[t2].next=h2[aa];
        h2[aa]=t2++;
    }
    int dfn[maxn],low[maxn],dfnc,sta[maxn],top;
    int js,shuyu[maxn],siz[maxn];
    ll a[maxn],ans[maxn];
    void tar(int xx){
        dfn[xx]=low[xx]=++dfnc;
        sta[++top]=xx;
        for(int i=h2[xx];i!=-1;i=b2[i].next){
            int u=b2[i].to;
            if(!dfn[u]){
                tar(u);
                low[xx]=min(low[xx],low[u]);
            } else if(!shuyu[u]){
                low[xx]=min(low[xx],dfn[u]);
            }
        }
        if(dfn[xx]==low[xx]){
            js++;
            while(sta[top]!=xx){
                int y=sta[top--];
                shuyu[y]=js;
                siz[js]++;
            }
            top--;
            shuyu[xx]=js;
            siz[js]++;
        }
    }
    queue<int> q;
    int vis[maxn];
    ll dis[maxn];
    void SPFA(int xx){
        q.push(xx);
        vis[xx]=1;
        while(!q.empty()){
            int now=q.front();
            q.pop();
            vis[now]=0;
            for(int i=head[now];i!=-1;i=b[i].next){
                int u=b[i].to;
                if(dis[u]<dis[now]+b[i].val){
                    dis[u]=dis[now]+b[i].val;
                    if(vis[u]==0){
                        q.push(u);
                        vis[u]=1;
                    }
                }            
            }
        }
    }
    int main(){
        memset(head,-1,sizeof(head));
        memset(h2,-1,sizeof(h2));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int aa,bb;
            scanf("%d%d",&aa,&bb);
            ad2(aa,bb);
        }
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tar(i);
        }
        for(int i=1;i<=n;i++){
            ans[shuyu[i]]+=a[i];
        }
        for(int i=1;i<=n;i++){
            for(int j=h2[i];j!=-1;j=b2[j].next){
                int u=b2[j].to;
                if(shuyu[i]!=shuyu[u]){
                    ad(shuyu[i],shuyu[u],ans[shuyu[u]]);
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=0;i<maxn;i++){
            dis[i]=-0x3f3f3f3f3f3f3f3f;
        }
        int s,p;
        scanf("%d%d",&s,&p);
        dis[shuyu[s]]=ans[shuyu[s]];
        SPFA(shuyu[s]);
        ll mans=0;
        for(int i=1;i<=p;i++){
            int aa;
            scanf("%d",&aa);
            mans=max(mans,dis[shuyu[aa]]);
        }
        printf("%lld
    ",mans);
        return 0;
    }
    

    C、测绘

    题目描述


    分析

    这一道题非常显然是一道DP题
    我们设(f[i][j])为前(i)个数中已经选择了(j)个数的价值,并且处于(i)位置上的数一定选择
    那么就有$ f[i][j]= min (f[i][j],f[k][j-1]+sum[k][i]);( 其中)j-1 leq k < i( )sum[i][j](为选走)i,j(位置上的数,区间)[i,j](中的数产生的误差 这一道题要注意初始化和最后的处理 我们需要将)f[i][1](和)f[i][i](预处理一下 同时,当)DP$结束后,因为最右边的价值没有计算,所以我们需要把最右边的价值加上

    100分代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=105;
    int n,vis[maxn],jud;
    ll e,a[maxn],sum[maxn][maxn],f[maxn][maxn];
    int main(){
        memset(f,0x3f,sizeof(f));
        scanf("%d%lld",&n,&e);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                for(int k=i+1;k<j;k++){
                    sum[i][j]+=abs(a[k]*2-a[i]-a[j]);
                }
            }
        }
        for(int i=1;i<=n;i++) f[i][i]=0;
        for(int i=1;i<=n;i++){
            f[i][1]=0;
            for(int j=1;j<i;j++){
                f[i][1]+=2*abs(a[i]-a[j]);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                for(int k=j-1;k<i;k++){
                    f[i][j]=min(f[i][j],f[k][j-1]+sum[k][i]);
                }
            }
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<=i;j++){
                ll ans=0;
                for(int k=i+1;k<=n;k++){
                    ans+=2*abs(a[k]-a[i]);
                }
                f[i][j]+=ans;
            }
        }
        int jl=n;
        ll ans=0;
        for(int i=1;i<=n;i++){
            ll now=0x3f3f3f3f3f3f3f3f;
            for(int j=i;j<=n;j++){
                now=min(now,f[j][i]);
            }
            if(now<=e){
                ans=now;
                jl=i;
                break;
            }
        }
        printf("%d %lld
    ",jl,ans);
        return 0;
    }
    

    D、奖学金



    分析

    数据范围高达 10 万,显然至少是(O(n∗log(n))) 才能通过。
    我们分析性质中位数 (ai) 必须满足:(n2+1≤i≤C−n2)
    (i=n2+1) 时,我们必须选上最小分数最低的前 (n2) 的猪。
    所以我们可以枚举每一个中位数,用一个维护奖金的大根堆,每枚举完一个中位数,如果当前的奖金比堆顶的小,则交换,始终保证堆的有 (n2) 个数,同时用一个数组 (f[i]) 维护如果选 (ai) 为中位数,前 (n2) 个数的最小奖金。
    同上,倒序维护,求出 (g[i]) 表示,如果选 (ai) 为中位数,则后 (n2) 个数最小奖金。
    显然答案为满足 (f[i]+g[i]+a[i].w<=F) 的最大的 (a[i].s)

    代码

    #include <bits/stdc++.h>
    const int maxn=2e5+5;
    int n,c,F;
    std::priority_queue <int> q;
    struct Node{
        int s,w;//分数,奖金
    } a[maxn];
    bool cmp(const Node &a, const Node &b){
        return a.s<b.s;
    }
    int f[maxn],g[maxn],sum;;
    void Init(){
        scanf("%d%d%d", &n,&c,&F);
        for(int i=1;i<=c;++i)
            scanf("%d%d", &a[i].s,&a[i].w);
        std::sort(a+1,a+1+c,cmp);//按成绩升序
    }
    void Solve(){
        for(int i=1;i<=n/2;++i){//成绩最低的n/2进入队列
            sum+=a[i].w;//累加总奖金
            q.push(a[i].w);//队列是维护奖金的大根堆
        }
        //f[i]:表示以i为中位数前n/2人的最小奖金
        for(int i=n/2+1;i<=c;++i){
            f[i]=sum;
            int top=q.top();
            if(top>a[i].w){//如果当前的奖金小于堆顶则交换掉
                q.pop();
                sum-=top;
                sum+=a[i].w;
                q.push(a[i].w);
            }
        }
    
        sum=0;
        while(!q.empty()) q.pop();
        for(int i=c;i>=c-n/2+1;--i){//成绩最高的n/2进入队列
            sum+=a[i].w;
            q.push(a[i].w);
        }
        //g[i]:表示以i为中位数后n/2人的最低奖金
        for(int i=c-n/2;i>=1;--i){
            g[i]=sum;
            int top=q.top();
            if(top>a[i].w){//交换
                q.pop();
                sum-=top;
                sum+=a[i].w;
                q.push(a[i].w);
            }
        }
        //中位数的取值范围是[n/2+1,c-n/2]
        //因为要求最大中位数,所以倒序
        for(int i=c-n/2;i>=n/2+1;--i)
            if(a[i].w+f[i]+g[i]<=F){
                printf("%d", a[i].s);
                return;
            }
        printf("-1
    ");
    }
    int main(){
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    linux 常用awk命令
    plsql连接oralce数据的配置 PLSQL配置怎么连ORACLE plsql连接多个数据库设置 Oracle 服务命名(别名)的配置及原理,plsql连接用
    PLSQL连接ORACLE配置字符串简介 oracle网络配置 三个配置文件 listener.ora、sqlnet.ora、tnsnames.ora原理解释
    OLEDB和ODBC的区别(优缺点)
    ADO,OLEDB,ODBC,DAO,RDO的区别说明
    Android开发在路上:少去踩坑,多走捷径
    手机淘宝构架演化实践
    车​险​与​非​车​险​基础分​类​和​说​明
    192.168.1.1地址,路由器地址打不开怎么办?
    一般测试流程 常用的软件测试工具有哪些? 开源测试工具 软件测试一般用到的工具、框架、技术列表
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13203250.html
Copyright © 2011-2022 走看看