• 【洛谷】P3537 [POI2012]SZA-Cloakroom


    题目描述
      有n件物品,每件物品有三个属性a[i], b[i], c[i] (a[i]<b[i])。
      再给出q个询问,每个询问由非负整数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]<=10^9)。
      下面一行一个正整数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

    分析

      看起来像个背包,但是它是有限制的。

      所以这并不是难不难的问题,它就是那种,被大佬们称作‘有限制的背包问题’的东西

      由于物品无序,所以对于第一个限制,可以按a从小到大排序,一个一个放入背包并记录,回答时直接二分一下位置就好了。

      我们发现这个题目比以往的题目少了一条限制,即物品的个数。

      而且k很小,这个题只需要回答yes和no

      所以直接考虑dp[i][j],表示选前i个物品c的和为j时,所用物品的b的最大值,直接转移即可

      这样的话,对于每个问题,

      第一个限制直接二分得到a中最后一个小于等于m的位置i

      第二个直接看dp[i][k]是否大于m+s,大于则输出yes,反之输出no。

      但发现好像内存开不下,所以离线处理询问,再像完全背包一样去dp,一边做一边记录答案

      代码如下,感觉细节贼多。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1005;
    struct node{int m,k,s,id;}que[1000005];
    int n,Q,a[maxn],b[maxn],c[maxn],q[maxn],w[maxn],ans[1000005],dp[100005];
    bool cmp(int x,int y){return a[x]<a[y];}
    bool cmp1(node a,node b){return a.m<b.m;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d%d%d",&c[i],&a[i],&b[i]),w[i]=a[q[i]=i];
        scanf("%d",&Q);for(int i=1;i<=Q;i++)scanf("%d%d%d",&que[i].m,&que[i].k,&que[i].s),que[i].id=i;
        sort(w+1,w+1+n);sort(q+1,q+1+n,cmp);sort(que+1,que+1+Q,cmp1);
        int K=1;
        dp[0]=1e9;
        for(int i=1,sum=0;i<=n;i++)
        {
            while(K<=Q&&que[K].m<w[i])ans[que[K].id]=(dp[que[K].k]>que[K].m+que[K].s),K++;
            sum+=c[q[i]];sum=min(sum,100000);
            for(int j=sum;j>=c[q[i]];j--)
            dp[j]=max(dp[j],min(dp[j-c[q[i]]],b[q[i]]));
        }
        while(K<=Q)ans[que[K].id]=(dp[que[K].k]>que[K].m+que[K].s),K++;
        for(int i=1;i<=Q;i++)if(ans[i])puts("TAK");else puts("NIE");
    }
  • 相关阅读:
    JAVA-JSP内置对象之response对象
    JAVA-JSP内置对象之request对象的其他方法
    JAVA-JSP内置对象之request获得封装所有参数值的Map
    JAVA-JSP内置对象之request获得参数的所有参数值(多个值)
    JAVA-JSP内置对象之request获得参数的参数值(一个值)
    Animator根骨骼运动原始实现代码
    Unity胶囊体的碰撞检测实现
    Animation Play/Stop测试
    texconv下载以及使用命令
    unity替换mesh测试
  • 原文地址:https://www.cnblogs.com/firecrazy/p/11623290.html
Copyright © 2020-2023  润新知