看似二分实则暴力的放木块问题(贪心)

例一:

传送门

题意:

就是给你$n$个物品,每一个物品都有一个体积$v[i]$,然后给你$m$个箱子,问你这个箱子的最小的体积是多少才能将这些物品都放到这m个箱子里

n,m(1≤n,m≤1000),v1,v2…,vn ( 1≤v1,v2,…,vn≤1000)


1 5 3 1 2 3 4 5

Case #1: 5

题解:

乍一看这个题是个二分,实则就是一个暴力的题,直接从小到大枚举答案就行

主要是这个贪心判断的过程,从大到小依次枚举这些物品,然后能装就装,这样来判断就行

int judge(ll x){
    init();
    for(int i=1;i<=m;i++){
        ll xx=x;
        for(int j=n;j>=1;j--){
            if(xx-a[j]>=0&&!vis[j]){
                vis[j]=1;
                xx-=a[j];
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            return 0;
        }
    } 
    return 1;
}

Code

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e4+100;
ll a[maxn];
int vis[maxn];
ll n,m;
void init(){
    for(int i=1;i<=n;i++){
        vis[i]=0;
    }
}
int judge(ll x){
    init();
    for(int i=1;i<=m;i++){
        ll xx=x;
        for(int j=n;j>=1;j--){
            if(xx-a[j]>=0&&!vis[j]){
                vis[j]=1;
                xx-=a[j];
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            return 0;
        }
    } 
    return 1;
}
int main(){
    int t;
    cin>>t;
    int kase=0;
    while(t--){
        cin>>n>>m;
        ll sum=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        sort(a+1,a+n+1);
        ll ans=1;//这有一个细节
        for(ll i=sum/m;i<=sum;i++){
            if(judge(i)){
                ans=i;    
                break;
            }
        } 
        printf("Case #%d: %lld\n",++kase,ans);
    }
}

 

 

例二:

传送门

这个题和那个差不多的,这个题是给了你这个箱子的体积,然后让你求最少需要几个箱子

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=5e6+100;

int a[maxn];
int b[220];
int c[maxn];
inint(){
    b[0]=1;
    for(int i=1;i<=20;i++)
    {
        b[i]=2*b[i-1];
    }
} 
int main()
{
    int t;
    inint();
    int n;
    cin>>t;
    while(t--)
    {
        int w;
        cin>>n>>w;
        for(int i=0;i<=20;i++)
            c[b[i]]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            c[a[i]]++;
        }
        int x;
        int ans=0;
        int lv=n;
        int s;
        while(1)
        {
            x=w;
            for(int i=20;i>=0;i--)
            {
                s=min(c[b[i]],x/b[i]);
                lv-=s;
                c[b[i]]-=s;
                x-=s*b[i];
            }
            ans++;
            if(lv==0)
                break;
        }
        printf("%d\n",ans);
    }
    return 0;
}
 

 

posted @ 2021-08-15 11:44  lipu123  阅读(53)  评论(0)    收藏  举报