zoukankan      html  css  js  c++  java
  • 18寒假12测

    Day1

    题目名称

    party

    array

    treasure

    输入

    party.in

    array.in

    treasure.in

    输出

    party.out

    array.out

    treasure.out

    每个测试点时限

    1秒

    1秒

    1秒

    内存限制

    64MB

    64MB

    64MB

    测试点数目

    10

    10

    10

    每个测试点分值

    10

    10

    10

    是否有部分分

    题目类型

    传统

    传统

    传统

     

     

    party

    题目描述:

    在M公司里,每个人只有一个直属上司(除了boss)。这个公司举办派对,每个人可以给派对带来一定的欢乐值,但是每个人不能和自己的上司同时参加这个派对,求派对的最大欢乐值。

    输入:

          第一行n表示公司有n个人。

    第二行n个数,表示每个人的上司是谁,如果这个人的上司为0,说明这个人是boss。

          第三行n个数,表示每个人的欢乐值为wi。

    输出:

    一行一个数表示最大欢乐值。

    样例输入:

    6

    0 1 1 1 4 4

    1 1 1 1 1 1

    样例输出:

    4

    解释:2 3 5 6 同时出席。

    数据规模:

    对于30%的数据,n<=20。

    对于100%的数据,n<= 1000000,0<=w[i]<=1000。

    题解:树形dp,dp[i][0/1]表示i号节点来不来,若父亲来,儿子肯定不来,若父亲不来,儿子随便来不来;

    dp[i][0] = sum( max (dp[son[i]][0], dp[son[i]][1]); dp[i][1] = sum(dp[son[i]][0]);

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1000005;
    int head[maxn],tot,dp[maxn][2];
    struct edge{
        int to,nxt;
    }G[maxn + 100];
    void add(int u,int v){
        G[++tot].nxt = head[u];
        G[tot].to = v;
        head[u] = tot;
    }
    void dfs(int u, int f){
        
        for(int i = head[u]; i; i = G[i].nxt){
            int v = G[i].to;
            //if(v == f)continue;
            dfs(v, u);
            dp[u][1] += dp[v][0];
            dp[u][0] += max(dp[v][0], dp[v][1]);
        }
    }
    int main(){
        freopen("party.in","r",stdin);
        freopen("party.out","w",stdout);
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            int fa;
            scanf("%d",&fa);
            add(fa, i);
        }
        for(int i = 1; i <= n; i++){
            int w;
            scanf("%d",&w);
            dp[i][1] = w;
        }
        dfs(0, 0);
        cout<<dp[0][0]<<endl;
    }

    array

    题目描述:

                给定两个长度为n的排列p1和p2,求它们的最长公共子序列。

    输入:

                第一行一个数n。

    接下来两个n个数分别表示p1和p2。

    输出:

                一个数表示最长子序列的长度。

    样例输入:

    3

    1 2 3

    2 1 3

    样例输出:

    2

    解释及说明:

    共有两种方案,分别为子序列为13和子序列为23.

    数据规模:

    对于30%的数据,n<=2000.

    对于100%的数据,n<=100000。

    题解:由于是排列,所以上下元素一样,且一个序列中无重复元素,我们就把一个序列的元素顺序做一个映射,在第二个序列中作最长上升子序列

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1000005;
    int d[maxn], mp[maxn], q[maxn], tail;
    int main(){
        freopen("array.in","r",stdin);
        freopen("array.out","w",stdout);
        int n, a, b;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            scanf("%d",&a);
            mp[a] = i;
        }
        for(int j = 1; j <= n; j++){
            scanf("%d",&b);
            d[j] = mp[b];
        }
        for(int i = 1; i <= n; i++){
            if(d[i] > q[tail])q[++tail] = d[i];
            else {
                int pos = lower_bound(q + 1, q + 1 + tail, d[i]) - q;
                q[pos] = d[i];
            }
        }
        cout<<tail<<endl;
    }
     

    treasure

    题目描述:

    小a可以攻打m座城堡,攻打每个城堡有不同的宝物,但是在攻打有些城堡前,需要攻打另外的城堡。小a想知道,能获得的最多宝物是多少?

    输入:

    第一行两个数,n,m。分别表示有n个城堡,可以攻打m个。

    接下来n行每行两个数a,b,分别表示在攻打第i个城堡前需要攻打a,攻打后获得b的宝物。

    输出:

    一行一个数ans表示可以获得的最大宝物数量。

    样例输入

    3 2

    0 1

    0 2

    0 3

    7 4

    2 2

    0 1

    0 4

    2 1

    7 1

    7 6

    2 2

    0 0

    样例输出:

    5

    13

     

    数据规模:

                对于30%的数据,n<=20,m<=20。

    对于100%的数据,n<=500,m<=500,b[i]<=1000。

    题解:树形DP,这道题很像树上染色,但不用考虑子树和外界 联系,要简单一点;

    dp[i][j]表示给i为根的子树分配j次攻打机会可获得最大的利益,答案就为dp[root][m];

    由于必须打父亲,才能打儿子,所以儿子可分配的机会为j-1,但0号点是我们假设的城堡,故他的子树有j次机会,特判一下,然后做一个分组背包就好了,因为一个子树分配的机会只能有一种方案;

    抽象一下:每个子树为一组,可供选择的物品为min(siz[father], j), 容量为min(siz[son],j);

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 505;
    int n,m;
    int head[maxn],tot,dp[maxn][maxn],siz[maxn];
    struct edge{
        int to,nxt,w;
    }G[maxn + 100];
    void add(int u,int v,int w){
        G[++tot].nxt = head[u];
        G[tot].to = v;
        G[tot].w = w;
        head[u] = tot;
    }
    void dfs(int u){
        for(int i = head[u]; i; i = G[i].nxt){
            int v = G[i].to;
            dfs(v); 
            int V = min(siz[u], m);
            int K = min(siz[v], m);
            for(int s = V; s >= 1; s--)
                for(int j = 1; j <= ( u == 0 ? min(s, K) : min(s-1, K) ); j++){
                    dp[u][s] = max( dp[u][s], dp[u][s - j] + dp[v][j] + G[i].w);
                }
                    
                
        }
    }
    void get_size(int u){
        siz[u] = 1;
        for(int i = head[u]; i; i = G[i].nxt){
            int v = G[i].to;
            get_size(v);
            siz[u] += siz[v];
        }
    }
    
    
    int main(){
        freopen("treasure.in","r",stdin);
        freopen("treasure.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++){
            int fa,w;
            scanf("%d%d",&fa,&w);
            add(fa, i, w);        
        }
        get_size(0);
        dfs(0);
        cout<<dp[0][m]<<endl;
    }

    考试突然不会分组背包了,╮(╯▽╰)╭, 一定要记得容量放外面,从大到小啊

  • 相关阅读:
    jQuery 小特效【文本框折叠隐藏,展开显示】【下拉菜单】【颜色渐变】【弹窗+遮罩】
    jQuery 【事件】【dom 操作】
    jQuery 【选择器】【动画】
    LINQ 小项目【组合查询、分页】
    LINQ 【高级查询】
    LINQ 【增、删、改、查】数据绑定
    WebFrom 【文件上传】
    【转】c# 字符串大小写混合转换
    【转】C#之继承
    类库,通用变量,is/as运算符,委托。
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8502658.html
Copyright © 2011-2022 走看看