zoukankan      html  css  js  c++  java
  • 长沙理工大学第十二届ACM大赛-重现赛 L

    题目描述

    小L有严重的选择困难症。
    早上起床后,需要花很长时间决定今天穿什么出门。
    假设一共有k类物品需要搭配选择,每类物品的个数为Ai,每个物品有一个喜欢值Vj,代表小L对这件物品的喜欢程度。
    小L想知道,有多少种方案,使得选出来的总喜欢值>M
    需要注意,每类物品,至多选择1件,可以不选。
     

    输入描述:

    多组输入
    每组数据第一行输入k M(k<=6,1<=M<=1e8),表示有多少类物品
    接下来k行,每行以Ai(1<=Ai<=100)开头,表示这类物品有多少个,接下来Ai个数,第j个为Vj(1<=Vj<=1e8),表示小L对这类物品的第j个的喜欢值是多少。

    输出描述:

    每组输出一行,表示方案数
    示例1

    输入

    2 5
    3 1 3 4
    2 2 3
    2 1
    2 2 2
    2 2 2

    输出

    3
    8

    题解

    折半搜索,二分。

    物品分两堆,$[1,k/2]$一起处理,$[k/2+1,k]$一起处理。每一堆暴力处理出$100$万种选择的可能,然后枚举一边,二分另一边即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    int k;
    long long m;
    
    long long v[10][200];
    int a[10];
    long long p[2][1100000];
    int sz0, sz1;
    
    void dfs0(int x, long long y) {
      if(x == k / 2 + 1) {
        p[0][sz0 ++] = y;
        return;
      }
      for(int i = 0; i <= a[x]; i ++) {
        dfs0(x + 1, y + v[x][i]);
      }
    }
    
    void dfs1(int x, long long y) {
      if(x == k + 1) {
        p[1][sz1 ++] = y;
        return;
      }
      for(int i = 0; i <= a[x]; i ++) {
        dfs1(x + 1, y + v[x][i]);
      }
    }
    
    int main() {
      while(~scanf("%d%lld", &k, &m)) {
        for(int i = 1; i <= k; i ++) {
          scanf("%d", &a[i]);
          for(int j = 1; j <= a[i]; j ++) {
            scanf("%lld", &v[i][j]);
          }
        }
        if(k == 1) {
          int sum = 0;
          for(int j = 1; j <= a[1]; j ++) {
            if(v[1][j] > m) sum ++;
          }
          printf("%d
    ", sum);
          continue;
        }
        sz0 = sz1 = 0;
        dfs0(1, 0);
        dfs1(k / 2 + 1, 0);
    
        sort(p[1], p[1] + sz1);
    
        long long ans = 0;
        for(int i = 0; i < sz0; i ++) {
          int L = 0, R = sz1 - 1, pos = sz1;
          while(L <= R) {
            int mid = (L + R) / 2;
            if(p[0][i] + p[1][mid] > m) pos = mid, R = mid - 1;
            else L = mid + 1;
          }
          ans = ans + (sz1 - pos);
        }
        printf("%lld
    ", ans);
    
      }
      return 0;
    }
    

      

  • 相关阅读:
    计算位数
    素数的判断(大数据,大规模)
    Patting Heads
    Jury Jeopardy (这是一道单纯的模拟题)
    POJ 2229 Sumsets(规律)
    OJ 26217 :Work Scheduling(贪心+优先队列)
    牛客Professional Manager(并查集)
    DJ 算法的队列优先优化
    优先队列priority_queue的简单应用
    node.js服务端存储用户密码md5加密
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8120292.html
Copyright © 2011-2022 走看看