zoukankan      html  css  js  c++  java
  • 20181029 考试记录

    题目pdf

    W神爷的题解

    T1:简单$dfs$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int a1[80],b1[80],a2[80],b2[80];
    int n,m,num[102];
    bool check(){
        int ans=0;
        for(int i=0;i<=12;i++){
            if(num[i]>0) ans+=num[i];
            if(!num[i]) break;
        }
        if(ans==n+m) return 1;
        return 0;
    }
    void dfs(int pos)
    {
        if(check()){
            cout<<"Yes";
            exit(0);
            return;
        } 
        if(pos==m+1) return;
        if(!a2[pos]) {
            dfs(pos+1);
            return;
        }
        dfs(pos+1);
        for(int i=1;i<=n;i++){
            if(b1[i]!=0){
                int t2=b2[pos],t1=b1[i];num[b1[i]]--;num[b2[pos]]--;
                b1[i]-=a2[pos];
                if(b1[i]<0) b1[i]=0;
                num[b1[i]]++;
                b2[pos]-=a1[i];
                if(b2[pos]<0) b2[pos]=0;
                num[b2[pos]]++;
                
                dfs(pos+1);
                num[b2[pos]]--;
                num[b1[i]]--;
                b1[i]=t1;
                b2[pos]=t2;
                num[b2[pos]]++;
                num[b1[i]]++;
                
            }
        }
    } 
    int main()
    {
        freopen("defile.in","r",stdin);
        freopen("defile.out","w",stdout);
        n=read(),m=read();
        for(int i=1;i<=n;i++) a1[i]=read(),b1[i]=read(),num[b1[i]]++;
        for(int i=1;i<=m;i++) a2[i]=read(),b2[i]=read(),num[b2[i]]++;
        dfs(1);
        cout<<"No";
        return 0;
    }
    View Code

    T2:

    (垃圾题目,$getchar$换成$scanf$,就$100 score$了)

    $kleq 15$,所以想到可以用状压$dp$来解决,第一步是要求每两个宝藏之间的距离,假设起点也是一个宝藏,用$bfs$解决,然后问题就转换成在一个完全图中选择$x$个点,使经过一次后距离不超过$T$,最大的$x$是多少。所以考虑状压$dp$,但是当只有一位($dp(i)$ 表示当前状态时是有后效性的,所以考虑二维)。

    设$dp(i,j)$表示当前取到的状态为$i$,最后一个点是$j$的最小距离。然后看一下当前距离是否小于$t$,若小于然后统计一下状态里的$1$即可.$dp(i,j)=dp(u,p)+dis(p,j) $,然后就瞎搞了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int n,m,k,t;
    int a[512][512];
    struct node{
        int x,y;
    }p[21];
    int sx,sy,sry=1,has[512][512],vis[512][512],dis[21][21];
    struct node1{
        int x,y,ans;
    };
    queue<node1> que;
    int dx[4]={1,-1,0,0};
    char str1[510];
    int dy[4]={0,0,1,-1};
    int dp[125537][21],d[21],inf=99999999,ans;
    int main()
    {
        n=read(),m=read(),k=read(),t=read();
        for(int i=1;i<=n;i++){
            scanf("%s",str1+1);
            for(int j=1;j<=m;j++){
                char str=str1[j];
                if(str=='#') a[i][j]=0;
                else a[i][j]=1;
                if(str=='*'){p[++sry].x=i,p[sry].y=j;has[i][j]=sry;}
                if(str=='S'){p[1].x=i,sx=i,sy=j,p[1].y=j;has[i][j]=1;}
            }
            getchar(); 
        }
        memset(dis,127/3,sizeof(dis));
        for(int st=1;st<=sry;st++){
            int px=p[st].x,py=p[st].y;
            memset(vis,0,sizeof(vis));
            while(!que.empty()) que.pop();
            node1 pig;
            pig.ans=0,pig.x=px,pig.y=py;
            vis[px][py]=1;
            que.push(pig);
            while(!que.empty()){
                int xx=que.front().x,yy=que.front().y,ff=que.front().ans;que.pop();
                for(int i=0;i<4;i++){
                    int tx=dx[i]+xx,ty=dy[i]+yy;
                    if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
                        if(vis[tx][ty]) continue;
                        if(!a[tx][ty]) continue;
                        vis[tx][ty]=1;
                        node1 fff;
                        fff.x=tx,fff.y=ty,fff.ans=ff+1;
                        que.push(fff);
                        if(has[tx][ty]){
                            dis[st][has[tx][ty]]=fff.ans;
                        }
                    }
                }
            }
        }
        memset(dp,127/3,sizeof(dp));
        dp[1][1]=0;
        for(int i=1;i<=(1<<sry)-1;i++){
            memset(d,0,sizeof(d));
            int st=0;
            for(int j=1;j<=sry;j++){
                if(i&(1<<(j-1))) d[j]=1,st++;
            }
            for(int j=1;j<=sry;j++){
                if(!d[j]) continue;
                d[j]=0;
                int zz=0,disdis=inf;
                for(int z=1;z<=sry;z++) zz+=(d[z]*(1<<(z-1))); 
                for(int z=1;z<=sry;z++){
                    if(d[z]) dp[i][j]=min(dp[i][j],dp[zz][z]+dis[z][j]);
                }
                d[j]=1;
                if(dp[i][j]<=t) 
                    ans=max(ans,st);
            }
        }
        cout<<ans-1<<endl;
    }
    View Code

    T3:

    其实就是一道比较简单的$dp$,结果看错了$A_i$的范围

    首先,先离散化,lower_bound即可,确定一下每个数,就是把他们存到$1~n$中。然后看见题目上说的是最小的最大,果断二分答案。我们假设$x$为二分的最小值,所以对于每一个位置$pos$,我们先设$st[pos]$表示右端点为$pos$的最小$l$值满足在$l~pos$中没有相同的数,其实就是这道题(this)。所以$pos$上一块的取值范围是$[st[pos]-1,pos-i]$,我们设$g(i)$表示前$i$个音符已经划定的方案数,及从$sum_{i=l}^r g(i)$,当前复杂度$O(n^2)$,考虑到$sum_{i=l}^r g(i)$这个式子可以前缀和优化,所以$dp$总复杂度$O(n)$,时间复杂度:$O(nlog(n))$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 998244353
    #include<algorithm>
    #define int long long
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int g[525011],sumg[525011],n,a[525011],x[525011],st[525011],last[525011];
    inline int get(int lim){
        memset(g,0,sizeof(g)),memset(sumg,0,sizeof(sumg));
        g[0]=sumg[0]=1;
        for(int i=1;i<=n;i++){
            int l=st[i]-1,r=i-lim;
            if(l>r) g[i]=0;
            else{
                if(l==0) g[i]=sumg[r];
                else g[i]=sumg[r]-sumg[l-1];
            }
            g[i]=(g[i]+mod)%mod;
            sumg[i]=sumg[i-1]+g[i];
            sumg[i]=(sumg[i]+mod)%mod;
        }return g[n]%mod;
    }
    bool check(int mid){return get(mid);}
    int maxn;
    signed main()
    {
        freopen("instrument.in","r",stdin);
        freopen("instrument.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) x[i]=a[i]=read();
        sort(x+1,x+n+1);
        for(int i=1;i<=n;i++) a[i]=lower_bound(x+1,x+n+1,a[i])-x;
        for(int i=1;i<=n;i++){
            st[i]=max(st[i-1],last[a[i]]+1);
            last[a[i]]=i;
        }
        int l=1,r=n;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid)) maxn=max(maxn,mid),l=mid+1;    
            else r=mid-1;
        }
        cout<<maxn<<endl<<(get(maxn)+mod)%mod;
        return 0;
    }
    View Code
  • 相关阅读:
    Java自定义加密字符串算法题目
    约瑟夫环C语言实现
    Java实现字符串形式大数相加
    Python打印乘法表
    Andorid中HandlerThread使用小记
    Ubuntu下C++使用icu库检测字符编码
    小记
    胆大妄为【DDWW】实验十 团队作业6:团队项目用户验收&Beta冲刺
    胆大妄为【DDWW】 【Beta】Scrum meeting 4
    胆大妄为【DDWW】 【Beta】Scrum meeting 3
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9872466.html
Copyright © 2011-2022 走看看