zoukankan      html  css  js  c++  java
  • Cloakroom

    Cloakroom

    题目描述

    • 有n件物品,每件物品有三个属性 a[i],b[i],c[i] (a[i]<b[i])。
    • 个询问,每个询问由非负整数 m,k,s 组成,问是否能够选出某些物品使得:
      1. 对于每个选的物品 i,满足 a[i]<=m 且 b[i]>m+s。
      2. 所有选出物品的 c[i]的和正好是 k。

    输入格式

    • 第一行一个正整数 n(n<=1,000),接下来 n 行每行三个正整数,分别表示 c[i],a[i],b[i] (c[i]<=1,000,1<=a[i]<b[i]<=109)。
    • 下面一行一个正整数 q(q<=1,000,000),接下来 q 行每行三个非负整数 m,k,s(1<=m<=(10^9),1<=k<=100,000,0<=s<=(10^9))。

    输出格式

    • 输出 q行,每行为 "TAK "(yes)或"NIE"(no),第 i 行对应第 i 次询问的答案。

    样例输入

    5
    6 2 7
    5 4 9
    1 2 4
    2 5 8
    1 3 9
    5
    2 7 1
    2 7 2
    3 2 0
    5 7 2
    4 1 5
    

    样例输出

    TAK
    NIE
    TAK
    TAK
    NIE
    

    Solve

    看这道题的题解都写的有些简单,特此补上一篇稍详细一些的题解(代码有注释)。

    • 题目大意

    n件物品分别有属性a,b,c.

    p个询问分别有属性m,k,s.

    对于每个询问给出是否存在满足以下三个条件的情况,有输出TAK,否则输出NIE

    1. 每个物品(a leq m)
    2. 每个物品(b>m+s)
    3. 所有物品c的和等于k
    • 解题思路

    • 考虑暴力,枚举k的所有组成情况并进行记录,每次询问仅须判断c的和为k的几个数,这样预处理都有(2^{1000}),妥妥49分TLE。

    • q[k][i].a表示和为k的第i种方案中所有物品a属性的最大值。
      q[k][i].b表示和为k的第i种方案中所有物品b属性的最小值。

    //...
    struct Node {
    	int a, b;
    	Node() {}
    	Node(int x, int y) {
    		a = x; b = y;
    	}
    };
    //...
    vector<Node> q[100005];//用q数组记录,便于查询
    void Dfs(int x, int big, int small, int sum) {
        if (big > small || sum > 100000) return;
        //剪枝优化,a比b大或总和超过数据范围就不再考虑
        q[sum].push_back(Node(big, small));
        for (int i = x + 1; i <= n; ++i)
            Dfs(i, max(big, a[i]), min(small, b[i]), sum + c[i]);
    }
    int main() {
        //...
        while (Q--) {
            int m, k, s, f = 0;
            scanf("%d%d%d", &m, &k, &s);
            for (int i = 0; i < q[k].size(); ++i)//枚举每种方案进行判断
                if (q[k][i].a <= m && q[k][i].b > m + s) f = 1;
            puts(f ? "TAK" : "NIE");
        }
        return 0;
    }
    //错误解法只列出关键部分,提供暴力思路
    
    • 这么大的数据,而且有3个条件需要满足,考虑离线算法。
    1. 看第一个条件:每个物品(a leq m)
      将物品按照a的大小排序,询问按照m的大小排序,这样,对于第一个条件满足当前询问的物品,也一定会满足后面的询问的第一个条件,节省了一些时间。

    2. 每个物品(b>m+s),先略过

    3. 所有物品c的和等于k
      类似于背包问题,需要把背包装满,可以按照背包的思路进行dp。

    • f[k]表示,在满足(a leq m)的物品中c属性之和为k的方案中最小的 b 属性的最大值

      • 这一点需要重点理解,需要满足每个物品(b>m+s),就需要最小的b比m+s大就可以,但是c属性的和为k的方案数有可能不止一种,需要找到最优的就是在满足x是这个方案中最小的b属性值的前提下尽可能的找x最大的方案。越说越迷糊,看代码可能会好懂一些。

    Code

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    struct Node1 {
        int a, b, c;
        bool operator < (const Node1 &b) const {
            return a < b.a;
        }//重载运算符,对物品按a值从小到大排序
    }a[1005];
    struct Node2 {
        int m, k, s, id;
        bool operator < (const Node2 &b) const {
            return m < b.m;
        }/重载运算符,对询问按m值从小到大排序
    }b[1000005];
    int n, q, f[100005];//f数组题解中的加粗部分进行了详细的解释
    bool ans[1000005];
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
            scanf("%d%d%d", &a[i].c, &a[i].a, &a[i].b);
        scanf("%d", &q);
        for (int i = 1; i <= q; ++i)
            scanf("%d%d%d", &b[i].m, &b[i].k, &b[i].s), b[i].id = i;
           //记录编号id,离线排序后便于保存答案
        sort(a + 1, a + n + 1);//对物品按a值从小到大排序
        sort(b + 1, b + q + 1);//对询问按m值从小到大排序
        f[0] = 1 << 30;//初始化f[0]为极大值,防止在运行 min(f[k-a[j].c], a[j].b)时出现结果都是0的情况
        for (int i = 1, j = 1; i <= q; ++i) {
            for (; j <= n && a[j].a <= b[i].m; ++j)//满足条件1:a<=m
                for (int k = 100000; k >= a[j].c; --k)
                    f[k] = max(f[k], min(f[k-a[j].c], a[j].b));
            if (f[b[i].k] > b[i].m + b[i].s) ans[b[i].id] = 1;
            //满足条件3:c之和==k
            //满足条件2:b>m+s
        }
        for (int i = 1; i <= q; ++i)
            puts(ans[i] ? "TAK" : "NIE");
        //三目运算符,个人比较喜欢使用,挺方便
        return 0;
    }
    
  • 相关阅读:
    'Undefined symbols for architecture i386,clang: error: linker command failed with exit code 1
    The codesign tool requires there only be one 解决办法
    XCode iOS project only shows “My Mac 64bit” but not simulator or device
    Provisioning profile XXXX can't be found 的解决办法
    UIView 中的控件事件穿透 Passthrough 的实现
    Xcode4.5出现时的OC新语法
    xcode 快捷键(持续更新)
    打越狱包
    php缓存与加速分析与汇总
    浏览器的判断
  • 原文地址:https://www.cnblogs.com/shawk/p/13337189.html
Copyright © 2011-2022 走看看