1. 程式人生 > >1110: [POI2007]砝碼Odw 貪心 思路題

1110: [POI2007]砝碼Odw 貪心 思路題

題解:

首先顯然是把砝碼從小到大裝進容器中,那麼如果我們能夠快速知道每次能否再放入砝碼,問題就迎刃而解了。題目有個重要條件:他們的中總有一個的重量是另外一個的整數倍,所以我們可以把每個容器用類似進位制轉換的方法表示,最高位的數字表示能裝最大的砝碼幾個,次高位表示儘量多的裝完最大砝碼,次大砝碼能裝的個數……以此類推,把所有容器的數加起來,然後每次裝入砝碼,相當於在某個位上 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); }