1110: [POI2007]砝码Odw 贪心 思路题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/82841146

题解:

首先显然是把砝码从小到大装进容器中,那么如果我们能够快速知道每次能否再放入砝码,问题就迎刃而解了。题目有个重要条件:他们的中总有一个的重量是另外一个的整数倍,所以我们可以把每个容器用类似进制转换的方法表示,最高位的数字表示能装最大的砝码几个,次高位表示尽量多的装完最大砝码,次大砝码能装的个数……以此类推,把所有容器的数加起来,然后每次装入砝码,相当于在某个位上 1 -1 ,贪心就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,m,a[Maxn],b[Maxn],c[40],d[40],e[Maxn],l=0;
bool check(int p)
{
    d[e[p]]--;
    int t=e[p];
    while(d[t]<0)
    {
        if(t==l)return false;
        d[t]+=c[t+1]/c[t];d[t+1]--;
        t++;
    }
    return true;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++)b[i]=read();
    sort(b+1,b+1+m);
    int last=0;
    for(int i=1;i<=m;i++)
    {
        if(b[i]==last){e[i]=l;continue;}
        c[++l]=last=b[i];e[i]=l;
    }
    for(int i=1;i<=n;i++)
    {
        int t=a[i];
        for(int j=l;j;j--)
        if(t>=b[j])d[j]+=t/c[j],t%=c[j];
    }
    int ans=0;
    for(int i=1;i<=m;i++)
    {
        if(check(i))ans++;
        else break;
    }
    printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/82841146