zoukankan      html  css  js  c++  java
  • 6.2 模拟赛

    6.2 模拟赛

    我试试吧

    A 多边形

    题意:给定一个多边形,点有点权,边有加和乘两种,表示边的端点可以通过权值加或乘合并为一个节点,求断掉某一条边形成的链不断合并节点最后能合并出的最大权值

    环形后效性处理+区间DP

    有极多细节,考场上没发现只拿了40pts(咬牙切齿

    考场上的代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=60;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int n,f[2*N][2*N],ans=0,val[2*N];
    bool typ[2*N];
    
    int main(){
    
        n=read();
        for(int i=1;i<=n;i++){
            char k;
            scanf("%c",&k);
            if(k=='t') typ[i]=0;
            else typ[i]=1;
            val[i]=read();
        }
        for(int i=n+1;i<=2*n;i++) typ[i]=typ[i-n],val[i]=val[i-n];
    
        for(int k=1;k<=n;k++){
            memset(f,0,sizeof f);
            for(int i=1;i<=2*n;i++) f[i][i]=val[i];
            // cout<<k<<endl;
            for(int len=2;len<=n;len++){
                for(int i=k;i<=k+n-len;i++){
                    int j=i+len-1;
                    for(int op=i+1;op<=j;op++){
                        // cout<<f[i][j]<<" ";
                        if(typ[op]==0) f[i][j]=max(f[i][j],f[i][op-1]+f[op][j]);
                        else f[i][j]=max(f[i][j],f[i][op-1]*f[op][j]);
                    }
                }
            }
            ans=max(ans,f[k][k+n-1]);
        }
    
        printf("%d
    ",ans);
        
        return 0;
    }
    
    

    还是想的太少了

    错误点:

    1. 数据中存在负数,负乘负得正,极小值有可能转移到极大值
    2. 没必要枚举删去的边,处理好答案之后可以直接查表
    3. 极小值的转移也有可能被极大值影响,要考虑到各种情况

    改以后的:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=60;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    ll n,f[2*N][2*N],ans=0,val[2*N],f2[2*N][2*N];
    bool typ[2*N];
    
    int main(){
    
        n=read();
        for(int i=1;i<=n;i++){
            char k;
            scanf("%c",&k);
            if(k=='t') typ[i]=0;
            else typ[i]=1;
            val[i]=read();
        }
        for(int i=n+1;i<=2*n;i++) typ[i]=typ[i-n],val[i]=val[i-n];
    
        memset(f,-0x3f,sizeof f);
        memset(f2,0x3f,sizeof f2);
        for(int i=1;i<=2*n;i++) f[i][i]=val[i],f2[i][i]=val[i];
        for(int len=2;len<=n;len++){
            for(int i=1;i+len-1<=2*n;i++){
                int j=i+len-1;
                for(int op=i+1;op<=j;op++){
                    if(typ[op]==0){
                        f[i][j]=max(f[i][j],f[i][op-1]+f[op][j]);
                        f2[i][j]=min(f2[i][j],f2[i][op-1]+f2[op][j]);
                    }else{
                        f[i][j]=max(f[i][j],f[i][op-1]*f[op][j]);
                        f[i][j]=max(f[i][j],f2[i][op-1]*f2[op][j]);
                        f2[i][j]=min(f2[i][j],f[i][op-1]*f2[op][j]);
                        f2[i][j]=min(f2[i][j],f2[i][op-1]*f[op][j]);
                        f2[i][j]=min(f2[i][j],f2[i][op-1]*f2[op][j]);
                    }
                }
            }
        }
        for(int i=1;i<=n;i++) ans=max(ans,f[i][i+n-1]);
    
        printf("%lld
    ",ans);
        
        return 0;
    }
    

    B 龙妹妹买牛奶

    题意:给定一棵树,选一些点,这些点之间的距离不能小于等于k,k取1或2

    树形DP k=1的时候很简单 k=2的时候很简单但是哪个都没拿全分

    考场上的码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=100010;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int k,n,e[N],ne[N],h[N],idx;
    int f[N][2],dp[N][2][2],biao[N][2];
    
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    
    void dfs1(int x,int fa){
        f[x][0]=0;
        f[x][1]=1;
        // cout<<x<<" "<<fa<<endl;
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            dfs1(j,x);
            f[x][1]+=f[j][0];
            f[x][0]+=max(f[j][1],f[j][0]);
        }
        return;
    }
    
    void dfs2(int x,int fa){
        memset(biao,0,sizeof biao);
        int sum=0;
        dp[x][0][0]=0;
        dp[x][0][1]=0;
        dp[x][1][0]=1;
        // cout<<x<<" "<<fa<<endl;
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            dfs2(j,x);
            biao[++sum][0]=dp[j][1][0];
            biao[sum][1]=biao[sum-1][1]+max(dp[j][0][1],dp[j][0][0]);
            dp[x][1][0]+=dp[j][0][0];
            dp[x][0][0]+=max(dp[j][0][1],dp[j][0][0]);
        }
        for(int i=1;i<=sum;i++){
            dp[x][0][1]=max(dp[x][0][1],biao[i][0]+biao[sum][1]-(biao[i][1]-biao[i-1][1]));
        }
        // cout<<endl<<x<<":"<<endl;
        // cout<<"1 0: "<<dp[x][1][0]<<endl;
        // cout<<"0 1: "<<dp[x][0][1]<<endl;
        // cout<<"0 0: "<<dp[x][0][0]<<endl;
        return;
    }
    
    void work1(){
        dfs1(1,0);
        printf("%d
    ",max(f[1][1],f[1][0]));
    }
    
    void work2(){
        dfs2(1,0);
        printf("%d
    ",max(dp[1][1][0],max(dp[1][0][1],dp[1][0][0])));
    }
    
    int main(){
    
        memset(h,-1,sizeof h);
    
        n=read();
        k=read();
        for(int i=1;i<n;i++){
            int a,b;
            a=read(),b=read();
            add(a,b);add(b,a);
        }
    
        if(k==1){
            work1();
        }else{
            work2();
        }
        
        return 0;
    }
    
    

    维生素B

    1. 我数组开小了

    2. 《k=2我A了一个点T了两个点WA了一个点但是我不知道我在推什么然后我看了看徐鰰的代码发现他的式子好像和我的一样》

    3. 我为啥要开三维数组

    改过以后的:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=100010;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int k,n,e[2*N],ne[2*N],h[2*N],idx;
    int f[2*N][2],biao[N];
    
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    
    void dfs1(int x,int fa){
        f[x][0]=0;
        f[x][1]=1;
        // cout<<x<<" "<<fa<<endl;
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            dfs1(j,x);
            f[x][1]+=f[j][0];
            f[x][0]+=max(f[j][1],f[j][0]);
        }
        return;
    }
    
    void dfs2(int x,int fa){//多么简洁多么赏心悦目的代码来自Xiwon
        f[x][0]=0;
        f[x][1]=1;
    
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            dfs2(j,x);
            biao[x]+=f[j][0];
        }
    
        f[x][0]=biao[x];
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            f[x][0]=max(f[x][0],f[j][1]+biao[x]-f[j][0]);
            f[x][1]+=biao[j];
        }
    
        return;
    }
    
    void work1(){
        dfs1(1,0);
        printf("%d
    ",max(f[1][1],f[1][0]));
    }
    
    void work2(){
        dfs2(1,0);
        printf("%d
    ",max(f[1][0],f[1][1]));
    }
    
    int main(){
    
        memset(h,-1,sizeof h);
    
        n=read();
        k=read();
        for(int i=1;i<n;i++){
            int a,b;
            a=read(),b=read();
            add(a,b);add(b,a);
        }
    
        if(k==1){
            work1();
        }else{
            work2();
        }
        
        return 0;
    }
    

    C 不要62

    题意:给你俩数,让你求俩数之间(包括俩数)数字中不含4和62的数的个数

    数位DP

    报零了/kk

    我上升吧

    考试的时候:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=15;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int l,r,f[N][N];
    
    void init(){
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int len=1;len<=7;len++)
            for(int i=0;i<10;i++)
                for(int j=0;j<10;j++)
                    if(i!=4&&(i!=6||j!=2)) f[len][i]+=f[len-1][j];
    }
    
    int cul(int x){
        if(x==-1) return 0;
        int op[N],len=0,res=0;
        int n=x;
        while(n){
            op[++len]=n%10;
            n/=10;
        }
        for(int i=len;i>0;i--){
            for(int j=0;j<op[i];j++){
                if(j!=4&&(j!=2||op[i+1]!=6)) res+=f[i][j];
            }
            if(op[i]==4||(op[i]==2&&op[i+1]==6)) break;
        }
        return res;
    }
    
    int main(){
    
        init();
    
        l=read(),r=read();
        while(l!=0||r!=0){
            //do something...
            printf("%d
    ",cul(r)-cul(l-1));
            l=read(),r=read();
        }
        
        return 0;
    }
    
    

    挺忙的

    1. cul()函数是求[0,x)的数,不是[0,x]
    2. cul()里面len+1的地方没定义,用到了会随机赋值,啥也不是

    改以后:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=15;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int l,r,f[N][N];
    
    void init(){
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int len=1;len<=7;len++)
            for(int i=0;i<10;i++)
                for(int j=0;j<10;j++)
                    if(i!=4&&!(i==6&&j==2)) f[len][i]+=f[len-1][j];
    }
    
    int cul(int x){
        int op[N],len=0,res=0;
        int n=x;
        while(n){
            op[++len]=n%10;
            n/=10;
        }
        op[len+1]=0;
        for(int i=len;i>0;i--){
            for(int j=0;j<op[i];j++){
                if(j!=4&&!(j==2&&op[i+1]==6)) res+=f[i][j];
            }
            if(op[i]==4||(op[i]==2&&op[i+1]==6)) break;
        }
        return res;
    }
    
    int main(){
    
        init();
    
        l=read(),r=read();
        while(l!=0||r!=0){
            //do something...
            printf("%d
    ",cul(r+1)-cul(l));
            l=read(),r=read();
        }
        
        return 0;
    }
    
    
    
  • 相关阅读:
    DIY 作品 及 维修 不定时更新
    置顶,博客中所有源码 github
    openwrt PandoraBox PBR-M1 极路由4 HC5962 更新固件
    使用 squid 共享 虚拟专用网至局域网
    第一次参加日语能力测试 N5
    libx264 libfdk_aac 编码 解码 详解
    开发RTSP 直播软件 H264 AAC 编码 live555 ffmpeg
    MFC Camera 摄像头预览 拍照
    http2 技术整理 nginx 搭建 http2 wireshark 抓包分析 server push 服务端推送
    plist 图集 php 批量提取 PS 一个个切
  • 原文地址:https://www.cnblogs.com/wsyunine/p/14843567.html
Copyright © 2011-2022 走看看