自己出的题 squee_spoon and his Cube III

本文介绍了一种使用动态规划解决比赛时间优化的问题。目标是将选手的比赛时间分配到三个时间段,使得最长的时间段最短。通过二维DP数组记录不同组合的可能性,并优化搜索过程减少不必要的计算。

        首先说下题意。就是一个比赛(安排得很紧凑),最多3个人同时比,每个人需要的时间是已知的,问最少总共花多少时间。或者可以想象成这样:三张桌子,一个选手比完下一个上。

        问题就可以转化为:有一些数,分为三组,需要使得和最大的那组尽可能小。

        这个问题可以通过dp(动态规划)来解决。dp(i,j)的第一维表示第一组的总时间,第二维表示第二组的总时间,第三组的总时间自然就是所有选手的时间之和减去前两组的时间。

        首先初态是dp[0][0]=true。此时三组为空,安排每个选手上台比赛,尝试把当前的选手的时间a加入每个组。如果加入第一组,就加在第一维上;如果加入第二组,就加在第二维上;如果加入第三组,不需要操作。即:

if(dp[i][j]==true){

dp[i+a][j]=true;

dp[i][j+a]=true;

}

        处理完所有选手后,我们就可以通过考察所有为true的dp[i][j],来找最小可能时间了。

        但是,如果仅仅做到这一步,还是会超时。需要进行一些优化。考虑三组的时间是可以互换的,设总时间为tot,我们可以让前两组的时间<=tot/3+60。下面是代码。

#include<iostream>   
#include<queue>   
#include<map>   
#include<set>   
#include<vector>   
#include<algorithm>   
#include<string.h>   
#include<cstdio>   
     
using namespace std;   
   
   
bool dp[1200][1200];
int a[60];
   
int main(){ 
    //freopen("test.in","r",stdin); 
    //freopen("test.out","w",stdout); 
    int n; 
    while(cin>>n){
        memset(dp,0,sizeof(dp));
        int tot=0; 
        int test=0; 
        for(int i=0;i<n;i++){ 
            scanf("%d",&a[i]); 
            tot+=a[i]; 
        } 
        int end = tot/3+60; 
         
        dp[0][0]=1;
        for(int k=0;k<n;k++){
            for(int i=end;i>=0;i--){
                for(int j=end;j>=0;j--){
                    if(dp[i][j]){
                        dp[i+a[k]][j]=1;
                        dp[i][j+a[k]]=1;
                    }
                }
            }
        }
         
        int ans=tot; 
        for(int i=0;i<=end;i++){
            for(int j=0;j<=end;j++){
                if(dp[i][j]){
                    int tmp=max(i,j);
                    tmp=max(tmp,tot-i-j);
                    ans=min(ans,tmp);
                }
            }
        }
         
        cout<<ans<<endl; 
    }
    return 0; 
} 

        这样就可以通过这道题了。如果想让程序跑得更快,可以进行进一步的优化,把合法状态专门存起来,不去扫描那些非法状态。

#include<iostream>   
#include<queue>   
#include<map>   
#include<set>   
#include<vector>   
#include<algorithm>   
#include<string.h>   
#include<cstdio>   
     
using namespace std;   
   
   
bool dp[1070][1070];
int a[60];
 
pair<int,int> piis[1100000];

int main(){ 
    //freopen("test.in","r",stdin); 
    //freopen("test.out","w",stdout); 
    int n; 
    while(cin>>n){
        memset(dp,0,sizeof(dp));
        int tot=0; 
        int test=0; 
        for(int i=0;i<n;i++){ 
            scanf("%d",&a[i]); 
            tot+=a[i]; 
        }
         
        int ans=tot; 
        int end = tot/3+60; 
        dp[0][0]=1;
        piis[0]=make_pair(0,0);
        int pos=1;
         
        for(int k=0;k<n;k++){
            for(int i=pos-1;i>=0;i--){
                int x,y;
                 
                x = piis[i].first + a[k];
                y = piis[i].second;
                if(x<y)swap(x,y);
                if(x<=end){
                    if(dp[x][y]==0){
                        dp[x][y]=1;
                        piis[pos++]=make_pair(x,y);
                        int tmp=max(x,y);
                        tmp=max(tmp,tot-x-y);
                        ans=min(ans,tmp);
                    }
                }
                 
                x = piis[i].first;
                y = piis[i].second + a[k];
                if(x<y)swap(x,y);
                if(x<=end){
                    if(dp[x][y]==0){    
                        dp[x][y]=1;
                        piis[pos++]=make_pair(x,y);
                        int tmp=max(x,y);
                        tmp=max(tmp,tot-x-y);
                        ans=min(ans,tmp);
                    }
                }
            }
        }
        cout<<ans<<endl; 
    }
    return 0; 
} 

        这道题算是这场比赛唯一有"算法"的题,可能出得难了。希望各位学弟学妹不要灰心,暂时的失败是再正常不过的。。不要因此放弃提高自己的机会。


import numpy as np import random class Particle: def __init__(self, object_value,particles_num): self.object_value = object_value self.particles_num = particles_num self.value = [] self.particles_create() def particles_create(self): for i in range(particles_num): self.value.append({ 'id': i+1, 'value': [random.randint(0,1) for _ in range(len(self.object_value))] }) class BPSOSA_CGOO: def __init__(self, object_weight, object_value, particles_num, bag_load, wc=0): self.object_weight = object_weight self.object_value = object_value self.particles_num = particles_num self.bag_load = bag_load self.wc = wc self.particles = [Particle(object_value, particles_num)] self.items = [] self.items_squee = [] self.create_items(object_value, object_weight) self.sort_items(self.items) self.pbest = self.particles.copy() self.pbest_value = [self.calculate_particle_value(particle) for particle in self.particles] self.gbest = self.particles[np.argmax(self.pbest_value)] self.gbest_value = max(self.pbest_value) #价值/重量 def create_items(self, object_value, object_weight): for i in range(len(object_value)): self.items.append({ 'id': i+1, 'density': object_value[i] / object_weight[i] }) def sort_items(self,items): self.items_squee = sorted(items, key=lambda x: x['density'], reverse=True) def calculate_particle_weight(self, particle): total_weight = sum(self.object_weight[j] * particle.value[j+1] for j in range(len(self.object_value))) return total_weight def calculate_particle_value(self, particle): total_value = sum(self.object_value[j] * particle.value[j+1] for j in range(len(self.object_value))) return total_value if __name__ == '__main__': object_weight = [95, 4, 60, 32, 23, 72, 80, 62, 65, 46] object_value = [55, 10, 47, 5, 4, 50, 8, 61, 85, 87] bag_load = 269 particles_num = len(object_weight)//2 BPSOSA_CGOO(object_weight, object_value, particles_num, bag_load)
最新发布
11-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值