【tyvj1032】零用钱 深搜+贪心

  • 背景

    • USACO OCT09 7TH
  • 描述

    -作為创造產奶纪录的回报,Farmer John决定开始每个星期给Bessie一点零花钱。

    FJ有一些硬币,一共有N (1 <= N <= 20)种不同的面额。每一个面额都能整除所有比它大的面额。

    他想用给定的硬币的集合,每个星期至少给Bessie某个零花钱的数目C (1 <= C <=
    100000000)。请帮他计算他最多能支付多少个星期的零花钱。

  • 输入格式

    -* 第一行: 两个由空格隔开的整数: N 和 C

    *第2到第N+1行: 每一行有两个整数表示一个面额的硬币:硬币面额V (1 <= V <=
    100,000,000)和Farmer John拥有的该面额的硬币数B (1 <= B <=
    1,000,000).

  • 输出格式

    -* 第一行: 一个单独的整数,表示Farmer John最多能给Bessie支付多少个星期至少為C的零用钱。

  • 输入

    • 3 6
      10 1
      1 100
      5 120
  • 输出

    • 111
  • 备注

    -FJ想要每个星期给Bessie六美分。他有100个1美分硬币,120个5美分硬币,和一个10美分硬币。

    FJ可以在一个星期超额付给Bessie一个10美分硬币。然后接下来的10个星期每星期付给
    Bessie两个5美分硬币。最后100个星期每星期付给Bessie一个1美分硬币跟一个5美分硬
    币。

tyvj1032

很容易想到的贪心:优先选最大的,对于剩下的钱总是选最大的但不超过c,最后用小的填上或超过c
总之就是不要让他花超太多

我打的dfs,实测证明tyvj评测机还是可以的hhh

代码内附第四个点的数据……
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int size=10010;
struct haha{
    int v,num;
}l[size],ll[size];
bool cmp(haha a,haha b)
{
    return a.v>b.v;
}
int n,c,ans=0;
int temp[size];
int div(int v)
{
    int tot=0;
    for(int i=1;i<=n;i++) 
    {
        if(l[i].num) temp[++tot]=l[i].v;
    }
    int s=0,t=tot;
    while(t-s>1)
    {
        int mid=(s+t)>>1;
        if(temp[mid]<v) t=mid;
        else s=mid;
    } 
    for(int i=1;i<=n;i++)
    {
        if(l[i].v==temp[t]) return i;
    }
}

bool dfs(int d)
{
    if(d>=c) 
    {
        ans++;
        return true;
    }
    for(int i=div(c-d);i<=n;i++)
    {
        if(l[i].num)
        {
            int k=min(l[i].num,(c-d)/l[i].v);
            if(k==0) k=1;
            l[i].num-=k;
            if(dfs(d+k*l[i].v)) return true;
            l[i].num+=k; 
        }
    }
    return false;
}

int main()
{
    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&ll[i].v,&ll[i].num);
    }
    sort(ll+1,ll+1+n,cmp);
    int tot=0;
    for(int i=1;i<=n;i++)
    {
        if(ll[i].v>=c) ans+=ll[i].num;
        else l[++tot]=ll[i];
    }
    n=tot;
    sort(l+1,l+1+n,cmp);
    while(dfs(0));
    //for(int i=1;i<=n;i++) cout<<l[i].v<<" "<<l[i].num<<endl; 

    printf("%d",ans);
    return 0; 
}
/* 3 6 10 1 1 1 5 21 20 100000000 67108864 1000000 33554432 1000000 16777216 1000000 8388608 1000000 4194304 1000000 2097152 1000000 1048576 1000000 524288 1000000 262144 1000000 131072 1000000 65536 1000000 32768 1000000 16384 1000000 8192 1000000 4096 1000000 2048 1000000 1024 1000000 512 1000000 256 1000000 128 1000000 */

你可能感兴趣的:(tyvj)