1. 程式人生 > >SPOJ:Decreasing Number of Visible Box(不錯的,背包?貪心?)

SPOJ:Decreasing Number of Visible Box(不錯的,背包?貪心?)

test case mini num collect con like clas pos 別人

Shadowman loves to collect box but his roommates woogieman and itman don‘t like box and so shadowman wants to hide boxes as many as possible. A box can be kept hidden inside of another box if and only if the box in which it will be held is empty and the size of the box is at least twice as large as the size of the box.

Print the minimum number of box that can be shown.

Input

The input set starts with single line integer T (1<=T<=50) the number of test cases. Then following T cases starts with an integer N (1<=N<=100000) denoting the number of box. The next line contains N space separated positive integer. i-th of them contains a numbers Ai(1<=Ai<=100000) size of the i-th box.

Output

Output the the case number and the minimum number of box that can be shown.

Example

Input:
2
4
1 2 4 8
4
1 3 4 5

Output:
Case 1: 1
Case 2: 3

題意:給定N個盒子,現在每個盒子最多可以裝一個盒子到內部,而且要滿足外面的盒子體積大於等於內部的盒子的兩倍。

思路:開始以為是平衡樹,每次在樹上找到一個大於等於兩倍體積的點,減減。但是復雜度太高,優化看一下也超時。最後又是手欠看了別人的代碼。

方法大概是,先排序,然後新建一個數組q,代表目前最小的盒子的兩倍,如果後面的盒子大於這個q,就可以把q裝進去,裝一次代表答案減一。

(主要是利用了單調性,貪心地裝目前最小的,秒啊。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int a[maxn],q[maxn],head,tail;
int main()
{
    int T,N,i,j,ans,Case=0;
    scanf("%d",&T);
    while(T--){
        head=tail=ans=0;
        scanf("%d",&N);
        for(i=1;i<=N;i++) scanf("%d",&a[i]);
        sort(a+1,a+N+1);
        for(i=1;i<=N;i++){
            if(head==tail) ans++;
            else if(q[tail+1]<=a[i]) tail++;
            else ans++;
            q[++head]=a[i]*2;
        }
        printf("Case %d: %d\n",++Case,ans);
    }
    return 0;
}

SPOJ:Decreasing Number of Visible Box(不錯的,背包?貪心?)