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

    6.9 模拟赛

    T1 叠虚

    并不知道叠虚是什么意思,有人来教教吗/kk

    没想到解法,只觉得这题搜索和DP都做不了,所以用堆维护,贪心了一下,没证明,贪错了(((

    正解给的是按力量值s和重量值w之和从小到大排序,排完序之后的序列就是从上至下的叠放顺序

    证明:

    [取原序列中某连续两人的风险值r_i和r_{i+1}\ 有r_i=sum_{j=1}^{i-1}w_j-s_i\r_{i+1}=sum_{j=1}^iw_j-s_{i+1}\ 令A=sum_{j=1}^{i-1}w_j\ 则r_i=A-s_i\r_{i+1}=A+w_i-s_{i+1}\ 若将两人调换位置,两人的风险值为r_i'和r’_{i+1}\ 有r'_{i+1}=A-s_{i+1}\r'_i=A+w_{i+1}-s_{i}\ 假设s_i+w_igeq s_{i+1}+w_{i+1}\ 即w_i-s_{i+1}geq w_{i+1}-s_i\ 所以r_{i+1}geq r'_i\ 又因为r_ileq r'_i,r_{i+1}geq r'_{i+1}\ 所以r_{i+1}geq r_i\ 调换前,r_{i+1}为最大风险值\ 调换后,r'_i和r'_{i+1}都比r_{i+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=100010;
    
    int n,ans=0;
    
    struct node{
        int w,s,ss;//ss是w和s的和
    }op[N];
    
    bool cmp(node a,node b){
        return a.ss<b.ss;//按ss排序
    }
    
    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 main(){
    
        n=read();
        for(int i=1;i<=n;i++) op[i].w=read(),op[i].s=read(),op[i].ss=op[i].w+op[i].s;
    
        sort(op+1,op+1+n,cmp);
        
        int pos=-op[1].s;
        ans=pos;
        for(int i=2;i<=n;i++){
            pos=(op[i-1].s+op[i-1].w+pos)-op[i].s;
            ans=max(ans,pos);
        }
    
        printf("%d
    ",ans);
    
        return 0;
    }
    

    T2 盖房子

    听说是luogu原题,没找着

    答案具有单调性,可以二分答案,判断的时候以行和列为单位判就可以了

    开longlong麻烦开全谢谢

    码:

    #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=1010;
    
    ll mapp[N][N];
    ll n,m,ans=0,maxx=0,minn=0x3f3f3f3ff,s[N];
    bool vis[N][N];//一列一行
    
    inline ll read(){
        ll 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;
    }
    
    bool check(ll x){//我就这一个地方没开ll,卡掉50pts
        memset(vis,false,sizeof(vis));
        int top;
        for(int i=1;i<=n;i++){
            top=0;
            for(int j=1;j<=m;j++) if(mapp[i][j]>=x) s[top++]=j;
            for(int j=0;j<top;j++){
                for(int k=j+1;k<top;k++){
                    if(vis[s[j]][s[k]]) return true;
                    vis[s[j]][s[k]]=true;
                }
            }
        }
        return false;
    }
    
    ll bisearch(){
        ll l=minn,r=maxx;
        while(l<r){
            ll mid=(l+r+1)>>1;
            if(check(mid)) l=mid;
            else r=mid-1;
        }
        return l;
    }
    
    int main(){
    
        n=read(),m=read();
    
        if(n<2||m<2) cout<<0<<endl,exit(0);
    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                mapp[i][j]=read(),maxx=max(maxx,mapp[i][j]),minn=min(minn,mapp[i][j]);
    
        printf("%lld
    ",bisearch());
        
        return 0;
    }
    

    T3 矿脉

    这个词我会(

    6e11可过

    题解给的是DP做法(O(n^4))

    我的是3e8过了

    考虑维护两个四维数组,先定左上点求最大,再以左上点为转移求答案,式子在代码里面

    题解:

    #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=55;
    
    int dp[N][N][N][N],n,m,s[N][N],q;
    int f[N][N][N][N];
    
    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 main(){
    
        n=read(),m=read(),q=read();
    
        memset(f,0,sizeof f);
        memset(dp,0,sizeof dp);
    
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=read();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                s[i][j]+=(s[i-1][j]+s[i][j-1]-s[i-1][j-1]);
            }
        }//二维前缀和
    
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                for(int l=1;l<=n;l++){
                    for(int r=1;r<=n;r++){
                      //这里
                        dp[i][j][l][r]=s[l][r]-s[i-1][r]-s[l][j-1]+s[i-1][j-1];
                        if(l-1>=i) dp[i][j][l][r]=max(dp[i][j][l][r],dp[i][j][l-1][r]);
                        if(r-1>=j) dp[i][j][l][r]=max(dp[i][j][l][r],dp[i][j][l][r-1]);
                      //这里
                    }
                }
            }
        }
    
    
        for(int i=n;i>=1;i--){
            for(int j=n;j>=1;j--){
                for(int l=1;l<=n;l++){
                    for(int r=1;r<=n;r++){
                      //这里
                        f[i][j][l][r]=dp[i][j][l][r];
                        if(i+1<=l) f[i][j][l][r]=max(f[i][j][l][r],f[i+1][j][l][r]);
                        if(j+1<=r) f[i][j][l][r]=max(f[i][j][l][r],f[i][j+1][l][r]);
                      //这里
                    }
                }
            }
        }
    
        for(int i=1;i<=q;i++){
            int a,b,c,d;
            a=read(),b=read(),c=read(),d=read();
            printf("%d
    ",f[a][b][c][d]);
        }
        
        return 0;
    }
    
    

    我哒:

    #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;
    
    int m,n,q,s[N][N];
    
    struct query{
        int x1,y1,x2,y2,ans;
    }qo[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;
    }
    
    void work(){
        int f[N][N];
        for(int d=1;d<=q;d++){
            for(int i=qo[d].y1;i<=qo[d].y2;i++)
                for(int j=i;j<=qo[d].y2;j++){
                        int sum=0;
                        for(int k=qo[d].x1;k<=qo[d].x2;k++){
                        if(sum>0) sum+=s[k][j]-s[k][i-1];
                        else sum=s[k][j]-s[k][i-1];
                        qo[d].ans=max(qo[d].ans,sum);
                    }
                }
        }
    }
    
    int main(){
    
        n=read(),m=read(),q=read();
    
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=read(),s[i][j]+=s[i][j-1];
        for(int i=1;i<=q;i++) qo[i].x1=read(),qo[i].y1=read(),qo[i].x2=read(),qo[i].y2=read(),qo[i].ans=-INF;
    
        work();
    
        for(int i=1;i<=q;i++) printf("%d
    ",qo[i].ans);
    
        return 0;
    }
    

    T4 食堂承包

    离谱的搜索,本来看着像多背包,但是数据不对劲而且价值都是1,以为搜索拿不了多少分然后就没写,然后XiEn1847随机化贪心拿了50pts,Orz

    搜索好题,几乎所有剪枝都用上了

    答案具有单调性可以二分答案

    直接DFS上

    剪枝:

    1. 对于一个二分出来的答案,我们选择体积更小的装入
    2. 二分上下界:上界:保证总容量能够包了体积最小的r个物品 下界:保证体积最小的l个物品装进容量最大的l个背包里
    3. 把价格相同的餐厅一起考虑
    4. 各种可行性剪枝

    码:

    #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=900010;
    
    int n,m,mon[N],w[N],smon=0,l,r,sw[N];
    
    bool cmp(int a,int b){
        return a>b;
    }
    
    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;
    }
    
    bool dfs(int x,int pre,int v,int tot){
        if(!x) return 1;
        if(smon-v<sw[tot]) return 0;
        int tmp=((w[x]==w[x+1])?pre:1);
        for(int i=tmp;i<=n;i++){
            if(mon[i]>=w[x]){
                mon[i]-=w[x];
                int t=((mon[i]<w[1])?mon[i]:0);
                if(dfs(x-1,i,v+t,tot)){
                    mon[i]+=w[x];
                    return 1;
                }
                mon[i]+=w[x];
            }
        }
        return 0;
    }
    
    bool check(int x){
        return dfs(x,1,0,x);
    }
    
    int main(){
    
        n=read();
        for(int i=1;i<=n;i++) mon[i]=read(),smon+=mon[i];
        m=read();
        for(int i=1;i<=m;i++) w[i]=read();
    
        sort(w+1,w+1+m);
        sort(mon+1,mon+n+1,cmp);
        
        for(int i=1;i<=m;i++) sw[i]=sw[i-1]+w[i];
    
        l=0,r=m;
    
        while(l<r){
            int mid=(l+r+1)>>1;
            if(check(mid)) l=mid;
            else r=mid-1;
        }
    
        printf("%d
    ",l);
        
        return 0;
    }
    
  • 相关阅读:
    李洪强经典面试题51-KVO-KVC
    李洪强经典面试题50-内存管理
    李洪强经典面试题49-Objective-C
    李洪强经典面试题48-C语言
    李洪强经典面试题47--UNIX常用命令
    李洪强经典面试题46-版本控制
    绿麻雀网贷系统通用注入分析
    跟着百度学PHP[5]函数篇2-PHP中的特殊形式的函数
    报错注入分析之(count()、rand()、group by)分析,被大佬称为floor报错注入
    跟着百度学PHP[5]函数篇1-参数
  • 原文地址:https://www.cnblogs.com/wsyunine/p/14869738.html
Copyright © 2011-2022 走看看