zoukankan      html  css  js  c++  java
  • 第四次模拟赛订正题解

    这次考动态规划专练;

    下一次考数据结构专练???

    坦白讲:这东西我还是不会;

    现在发现好像是一个叫做树的最大独立集的;

    有个暴力40分的做法,预处理所有的深度(层数),不是相邻层的累加,最后比较max,这个复杂度过不去,也只是贪心的思想,所以写完爆搜之后我还是去写了树形dp;

    我们用dp[i][K]表示当前节点i选择(k==1)或不选择(k==0);而且比较巧妙地是,在统计方案树的是否,我们直接可以用当前k的表示该节点的方案,累加即可,好妙啊;

    给出的题解:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000010
    vector<int> G[N];
    int n,u,v;
    
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch)) {if(ch=='-')  f=-1;  ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);  ch=getchar();}
        x*=f;
    }
    
    void dfs(int u,int fa) {
        for(int i=0;i<G[u].size();i++) {
            if(G[u][i]!=fa) {
                dfs(G[u][i],u);
            }
        }
    }
    
    int d[N][2]={0};
    int dp(int u,int k,int fa) {
        d[u][k]=k;
        for(int i=0;i<G[u].size();i++) {
            if(G[u][i]!=fa) {
                if(k){//如果选,子节点不选 
                    d[u][k]+=dp(G[u][i],0,u);
                }
                else{//如果不选,选子节点或不选子节点 
                    d[u][k]+=max(dp(G[u][i],0,u),dp(G[u][i],1,u));
                }
            }
        }
        return d[u][k];
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        read(n);
        for(int i=1;i<n;i++) {
            read(u); read(v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,-1);
        cout<<max(dp(1,0,-1),dp(1,1,-1));
        return 0;
    }
    View Code

    第二题:

    环形合并石子:区间dp;破环为链,复制一倍;

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
        while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
        x*=f;
    }
    int n,a[N],sum[N],h[N][N];
    int main() {
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
        read(n);
        memset(h,0xcf,sizeof(h));
        for(int i=1;i<=n;i++) 
            read(a[i]),a[i+n]=a[i];
        for(int i=1;i<=n*2;i++)
            sum[i]=sum[i-1]+a[i],h[i][i]=0;
        for(int len=2;len<=n;len++) 
            for(int l=1;l+len<=n*2+1;l++) {
                int r=l+len-1;
                for(int k=1;k<r;k++) {
                    h[l][r]=max(h[l][r],h[l][k]+h[k+1][r]+sum[r]-sum[l-1]);
                }
            }
        int ans2=-(1<<30);
        for(int i=1;i<=n;i++) {
            ans2=max(ans2,h[i][i+n-1]);
        }
        cout<<ans2<<endl;
        return 0;
    }
    View Code

    第三题:

    看数据范围:

    非常容易想到状压dp,本身就是一种暴力做法;

    dp[i][j]表示当前i状态下,最后一位放的是j,感觉好套路啊这样的状态;

    那么我们只需要判断当前状态下是否能放w,状态转移是累加方案即可;

    给出的题解:

    竟然考了状压dp;

    #include<bits/stdc++.h>
    using namespace std;
    #define N 20
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
        while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
        x*=f;
    }
    
    long long n,k,a[N],f[1<<N][N];
    long long ans;
    
    int main()
    {
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
        read(n); read(k);
        for(int i=1;i<=n;++i)  {
            read(a[i]);
            f[1<<(i-1)][i]=1;//第i位放i的方案初始化1 
        }
        for(int i=1;i<(1<<n);++i) {//枚举状态 
            for(int j=1;j<=n;++j) {//当前放j 
                for(int w=1;w<=n;++w) {//下一个放w 
                    if(i&(1<<(w-1))) continue;//如果当前状态下w位不能放w 
                    if(abs(a[j]-a[w])>k) {//满足题目要求的k可以放 
                        f[i|(1<<(w-1))][w]+=f[i][j];//更新状态,累加答案 
                    }
                }
            }
        }
        for(int i=1;i<=n;++i)  {
            ans+=f[(1<<n)-1][i];
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    最后祝贺Chdy大佬不到一个小时AK;

  • 相关阅读:
    POJ1579Function Run Fun
    C++ 程序员必读书目清单
    zoj2100Seeding(水题)
    接口开发及技术负责
    哪些需求最重要
    地址
    哪些需求最重要
    setTimeOut与 setInterval区别
    项目管理简介
    项目管理简介
  • 原文地址:https://www.cnblogs.com/Tyouchie/p/11076536.html
Copyright © 2011-2022 走看看