zoukankan      html  css  js  c++  java
  • 2018/7/19 模拟赛

    T1 动态规划+贪心。考场上写了个O(n^3)的,60分。设dp[i]表示以i为右端点的最大划分数,last[i]表示第i个数(指的是合并后)的大小。
    dp[i]=max(dp[j]+1) (sum[i]-sum[j]>=last[j])
    last[i]=sum[i]-sum[j],时间复杂度O(n^2)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 5005;
    typedef long long LL;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,a[MAXN],dp[MAXN],ans;
    LL sum[MAXN],last[MAXN];
    
    int main(){
        freopen("tower.in","r",stdin);
        freopen("tower.out","w",stdout);
        n=rd();
        for(register int i=1;i<=n;i++){
            a[i]=rd();
            sum[i]=sum[i-1]+a[i];
        }
        for(register int i=1;i<=n;i++){
            for(register int j=i-1;j>=0;j--)
                if(sum[i]-sum[j]>=last[j] && dp[i]<=dp[j]){
                    dp[i]=dp[j]+1;
                    last[i]=sum[i]-sum[j];
                }
        }
        printf("%d",n-dp[n]);
        return 0;
    }

    T2还是dp。。。考场上逗比了,多循环了n次。。28滚粗。。实际上挺简单的,dp[i][j]表示第i天有j的能力值的最大工作次数。因为工作可以随时并且不限次数,所以先预处理出每个能量下的最小工作时间best[i],然后转移中有三种选择,第一种是什么也不做,第二种是上课,第三种是工作,然后直接专业就行。时间复杂度O(S*t)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 10005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch))  {if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int t,s,n,m,ans;
    
    struct CLASS{
        int w,st,ed;
    }cla[MAXN];
    
    struct WORK{
        int wks,wke;
    }wor[MAXN];
    
    vector<int> cnt[MAXN];
    int dp[MAXN][105];
    int best[10005];
    
    inline bool cmp(WORK A,WORK B){
        return A.wke<B.wke;
    }
    
    int main(){
        freopen("wrk.in","r",stdin);
        freopen("wrk.out","w",stdout);
        memset(dp,-0x3f,sizeof(dp));
        memset(best,0x3f,sizeof(best));
        t=rd();s=rd();n=rd();
        for(register int i=1;i<=s;i++) {
            cla[i].st=rd();cla[i].ed=rd();cla[i].w=rd();
            cnt[cla[i].st].push_back(i);
            m=max(m,cla[i].w);
        }
        for(register int i=1;i<=n;i++){
            wor[i].wke=rd();wor[i].wks=rd();
            best[wor[i].wke]=min(best[wor[i].wke],wor[i].wks);
        }
        for(register int i=1;i<=m;i++)
            best[i]=min(best[i],best[i-1]);
        dp[0][1]=0;
        for(register int i=0;i<t;i++){
            for(register int j=1;j<=m;j++){
                if(i+best[j]<=t)
                    dp[i+best[j]][j]=max(dp[i+best[j]][j],dp[i][j]+1);
                for(vector<int>::iterator k=cnt[i].begin();k!=cnt[i].end();k++){
                    if(cla[*k].ed+i>t) continue;
                    int kk=cla[*k].w;
                    dp[cla[*k].ed+i][kk]=max(dp[cla[*k].ed+i][kk],dp[i][j]); 
                }
                dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
            }
        }
        for(register int i=1;i<=m;i++)
            ans=max(ans,dp[t][i]);
        printf("%d",ans);
        return 0;
    }

    T3 考场上最后没时间了(我不会告诉你我迟到了40分钟的qwq) 就拿了个n<=10的,给了三十。正解:我们可以先二分一个mid,可以观察到其实整个图就是一个菊花图,有一个点,给它连上各种链和树,假如是链的情况,那么这条链上所需要的树洞其实就是这条链的点数cnt/(2*mid+1)向上取整。因为只要在中间放点的话可以照顾到左右两边的mid再加上自己。然后只要枚举每个能覆盖花心的点,然后将它能覆盖的点打上标记,剩下只剩下几条链了,然后加起来判断。时间复杂度O(n^2)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<cstring>
    
    using namespace std;
    const int MAXN = 2005;
    const int MAXM = MAXN*MAXN;
    const int inf = 0x3f3f3f3f;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,head[MAXN],cnt,m,k,ans;
    int to[MAXM<<1],nxt[MAXM<<1];
    int mx,fl,du[MAXN],sum,ct,dis[MAXN];
    bool vis[MAXN];
    queue<int> Q;
    
    inline void add(int bg,int ed){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
    }
    
    inline void dfs(int x){
        vis[x]=1;ct++;
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];
            if(vis[u]) continue;
            dfs(u); 
        }
    }
    
    inline void find(int x,int Mid){
        vis[x]=1;
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];
            if(vis[u]) continue;
            if(dis[u]==inf) {
                ct=0;dfs(u);
                sum+=ct/((Mid<<1)+1);
                if(ct%((Mid<<1)+1)) sum++;
            }
            else find(u,Mid);
        }
    }
    
    inline bool check(int Mid){ 
        for(register int i=1;i<=n;i++){
            memset(dis,0x3f,sizeof(dis));
            memset(vis,false,sizeof(vis));
            Q.push(i);vis[i]=1;dis[i]=0;sum=0;  
            while(Q.size()){
                int x=Q.front();Q.pop();
                for(register int j=head[x];j;j=nxt[j]){ 
                    int u=to[j];    
                    if(vis[u] or ((dis[x]+1)>Mid)) continue;
                    vis[u]=1;dis[u]=dis[x]+1;Q.push(u);
                }   
            }
            if(!vis[fl]) continue;
            memset(vis,false,sizeof(vis));
            find(i,Mid);if(sum<k) return true;
        }
        return false;
    }
    
    int main(){
        freopen("holes.in","r",stdin);
        freopen("holes.out","w",stdout);
        n=rd();m=rd();k=rd();
        for(register int i=1;i<=m;i++){
            int x=rd(),y=rd();
            add(x,y);add(y,x);
            du[x]++;du[y]++;
            if(du[x]>mx)  {mx=du[x];fl=x;}
            if(du[y]>mx)  {mx=du[y];fl=y;}
        }
        int l=1,r=MAXM;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid)) {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    setTimeout,setInterval你不知道的…
    浏览器console的用法
    命题和命题的否定可以同时成立吗?
    Web云笔记--CSS
    dreamweaver代码提示失效
    游戏平台代表--PS4【推荐】
    Mac上好用的视频播放器有哪些?
    新浪博客“网络繁忙请稍后再试”
    人工智能成功识别“色情暴力”信息??…
    JS查错小工具-三生有幸【推荐】
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676940.html
Copyright © 2011-2022 走看看