The revised fourth race simulation solution to a problem

The test dynamic programming special training;

The next test data structure designed to practice? ? ?

Frankly: This thing I will not;

 

 

Now we find the tree seems to be called the largest independent set;

There is a violent 40 minutes of practice, all of the pre-depth (layers), not adjacent layers accumulate, the last relatively max, the complexity of the trouble, but also greedy thoughts, so after I finished the burst search to write the tree dp;

We dp [i] [K] represents the current selected node i (k == 1) or not selected (k == 0); and relatively skillfully is whether the statistical program tree, we can use the direct current of k It indicates that the node of the program, can be accumulated, good wonderful ah;

Problem solution is given:

#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;

 

Guess you like

Origin www.cnblogs.com/Tyouchie/p/11076536.html