zoukankan      html  css  js  c++  java
  • hihocoder 编程挑战赛75

    题目1

    内存限制:256MB

    描述

    H公司在北京和上海两个城市各有一间办公室。该公司最近新招募了2N名员工,小Hi负责把这2N名员工分配到北京和上海各N名。

    于是小Hi调查了新员工对于北京和上海的意愿,我们用Bi和Si表示。Bi代表如果分配第i名员工去北京,他的满意指数;Si代表如果分配去上海,他的满意指数。

    小Hi想知道如何分配才能使2N名员工的满意指数之和最高。

    输入

    第一行包含一个整数N。

    以下2N行每行包含两个整数Bi和Si。

    1 ≤ N ≤ 1000

    0 ≤ Bi, Si ≤ 100000

    输出

    一个整数代表最高可能的满意指数之和。

    测试样例

    样例输入

    2

    100 50

    80 80

    50 100

    10 30

    样例输出

    310

    题解

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN (1010)
    static int B[2 * MAXN], S[2 * MAXN];
    int sat[MAXN][MAXN];
    
    int main() {
        int n;
        while (cin >> n) {
            memset(B, 0, sizeof(B));
            memset(S, 0, sizeof(S));
            for (int i = 1; i <= 2 * n; i++) {
                cin >> B[i] >> S[i];
            }
            memset(sat, 0, sizeof(sat));
            for (int i = 1; i <= n; i++) {
                sat[i][0] = sat[i - 1][0] + B[i];
                sat[0][i] = sat[0][i - 1] + S[i];
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    sat[i][j] = max(sat[i][j - 1] + S[i + j],
                    sat[i - 1][j] + B[i + j]);
                }
            }
            cout << sat[n][n] << endl;
        }
        return 0;
    }

    题目2

    内存限制:256MB

    描述

    H公司在北京、上海和纽约三个城市各有一间办公室。该公司最近新招募了3N名员工,小Hi负责把这3N名员工分配到北京、上海和纽约各N名。

    于是小Hi调查了新员工对于北京、上海和纽约的意愿,我们用Bi、Si和Ni表示。Bi代表如果分配第i名员工去北京,他的满意指数;Si代表如果分配去上海的满意指数;Ni代表如果分配去纽约的满意指数。

    小Hi想知道如何分配才能使3N名员工的满意指数之和最高。

    输入

    第一行包含一个整数N。

    以下3N行每行包含两个整数Bi、Si和Ni。

    1 ≤ N ≤ 100

    0 ≤ Bi, Si, Ni ≤ 100000

    输出

    一个整数代表最高可能的满意指数之和。

    样例

    样例输入

    2

    100 50 100

    80 80 100

    50 100 100

    10 30 100

    80 40 30

    20 70 50

    样例输出

    550

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN (1010)
    static int B[2 * MAXN], S[2 * MAXN];
    int sat[MAXN][MAXN];
    
    int main() {
        int n;
        while (cin >> n) {
            memset(B, 0, sizeof(B));
            memset(S, 0, sizeof(S));
            for (int i = 1; i <= 2 * n; i++) {
                cin >> B[i] >> S[i];
            }
            memset(sat, 0, sizeof(sat));
            for (int i = 1; i <= n; i++) {
                sat[i][0] = sat[i - 1][0] + B[i];
                sat[0][i] = sat[0][i - 1] + S[i];
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    sat[i][j] = max(sat[i][j - 1] + S[i + j],
                    sat[i - 1][j] + B[i + j]);
                }
            }
            cout << sat[n][n] << endl;
        }
        return 0;
    }

    题目3

    hihocoder #1818 : 顺子组合

    问题来源URL

    http://hihocoder.com/problemset/problem/1818

    描述

    你有一个包含N个整数的数组:A1, A2, ... AN。我们将3个或3个以上数值连续的整数序列称作顺子,例如[1, 2, 3]、[5, 6, 7, 8]和[10, 11, 12, 13, 14, 15, 16]都是顺子。

    请你判断A数组是否能拆分成若干个顺子的组合。要求每个整数Ai恰好只属于其中一个顺子。

    输入

    第一行包含一个整数T代表测试数据的组数。  

    每组数据第一行包含一个整数N  

    每组数据第二行包含N个整数A1, A2, ... AN  

    1 ≤ T ≤ 10  

    1 ≤ N ≤ 10000  

    0 ≤ Ai ≤ 100000

    输出

    对于每组数据输出YES或者NO代表是否能拆分成顺子组合。

    测试样例

    样例输入

    2

    7

    4 1 3 2 5 4 6

    8

    4 1 3 2 5 4 6 6

    样例输出

    YES  
    
    NO
    

    题解

        顺子是扑克牌的一种排列顺序,指的是花色不一定相同的牌是一个连续的序列,该序列的长度还大于等于3。题目中的要求是让牌的划分序列每个的连续长度>=3。事实上,这个要求跟每个序列的长度都在3-5是等价的。如果能够满足3-5,则必然能满足>=3,因为3-5包含于>=3的情况;反过来,>=3的序列必然可以拆成3-5的序列。由于这个原因,我们找到了这个题的对应题目,http://codeforces.com/gym/101775/problem/J

        解决这道题,可以是按照如下思路:

        怎么把顺子合成一个序列,而不是拆分?显然,合成是非常简单的,顺子是一个表示个数的1序列,长度>=3,合成的话就是区间累加了。把它用差分序列表示的话,就是1,0,0,(至少有2个0)-1。最后得到的序列的差分,肯定是差分序列的叠加了。所以我们可以把它们累加起来,判断最后的和是否是等于0,并结合其他条件判定是多个顺子的组合。

    代码

    #include<stdio.h>
    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    int arr[MAXN];
    int differ[MAXN];
    int main() {
      int N, T;
      cin >> T;
      int a;
      for (int i = 0; i < T; i++) {
        cin >> N;
        memset(arr, 0, sizeof(arr));
        memset(differ, 0, sizeof(differ));
        int maxn = 0;
        for (int j = 0; j < N; j++) {
          cin >> a;
          maxn = max(a, maxn);
          arr[a]++;
        }
        for (int j = 0; j <= MAXN; j++) {
          differ[j + 1] = arr[j + 1] - arr[j];
        }
        differ[0] = arr[0];
        int t = 0;
        int sum = 0;
        for (int j = 0; j <= maxn; j++) {
          if (differ[j] > 0) sum += differ[j];
          if (j + 3 <= maxn + 1) {
            if (differ[j + 3] < 0) {
              sum += differ[j + 3];
              differ[j + 3] = 0;
            }
            if (sum < 0) break;
          }
        }
        #if 0
        for (int i = 0; i <= maxn; i++) {
          printf(" %d", differ[i]);
        }
        printf("
    ");
        #endif
        if (sum != 0) {
          cout << "NO
    ";
        } else {
          cout << "YES
    ";
        }
      }
      return 0;
    }

    测试

    3

    3

    0 1 2

    1

    10

    7

    0 1 2 3 9 10 11

    7

    0 1 2 3 5 6 8

    >>Output:

    YES

    YES

    NO

    题目4

    描述

    请你实现一个加强版的栈,支持以下操作:

    push x: 向栈顶加入一个整数x

    pop: 从栈顶弹出一个整数,并且输出该整数

    inc k x: 将处于栈底的前k个整数加x。

    输入

    第一行包含一个整数N,代表操作的数量。

    以下N行每行一条操作。

    1 ≤ N ≤ 200000, 0 ≤ x ≤ 100000, 1 ≤ k ≤ 当前栈的大小

    输出

    对于每一个pop操作,输出弹出的整数数值。

    测试样例

    样例输入

    6

    push 1

    inc 1 2

    push 2

    inc 2 2

    pop

    pop

    样例输出

    4

    5

    题解

    即使想用线段树也显得多余,因为在栈的操作中其实有一个很简单的特性就是每次只能pop一个,再加上问题中的条件是前k个增加值,所以并不会有需要利用线段树减少复杂度的情况。

    代码

    #include<stdio.h>
    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    int arr[MAXN];
    int differ[MAXN];
    int main() {
      int N, T;
      cin >> T;
      int a;
      for (int i = 0; i < T; i++) {
        cin >> N;
        memset(arr, 0, sizeof(arr));
        memset(differ, 0, sizeof(differ));
        int maxn = 0;
        for (int j = 0; j < N; j++) {
          cin >> a;
          maxn = max(a, maxn);
          arr[a]++;
        }
        for (int j = 0; j <= MAXN; j++) {
          differ[j + 1] = arr[j + 1] - arr[j];
        }
        differ[0] = arr[0];
        int t = 0;
        int sum = 0;
        for (int j = 0; j <= maxn; j++) {
          if (differ[j] > 0) sum += differ[j];
          if (j + 3 <= maxn + 1) {
            if (differ[j + 3] < 0) {
              sum += differ[j + 3];
              differ[j + 3] = 0;
            }
            if (sum < 0) break;
          }
        }
        #if 0
        for (int i = 0; i <= maxn; i++) {
          printf(" %d", differ[i]);
        }
        printf("
    ");
        #endif
        if (sum != 0) {
          cout << "NO
    ";
        } else {
          cout << "YES
    ";
        }
      }
      return 0;
    }

    参考

    http://codeforces.com/gym/101775/problem/J Straight Master

  • 相关阅读:
    实验一 网络侦查与网络扫描
    网络对抗作业一
    [BSidesCF 2020]Hurdles
    [BSidesCF 2019]Mixer
    安恒期末 admin
    C#编程:正则表达式验证身份证校验码-10
    分享1-3年经验的Java面试
    SpringMVC配置web.xml文件详解(列举常用的配置)
    Hibernate全套增删改查+分页
    Node.js连接mysql数据库方法
  • 原文地址:https://www.cnblogs.com/wangzming/p/9696763.html
Copyright © 2011-2022 走看看