算法装载问题:n个人,第i个人的体重为wi,每艘船的最大载重均为C,且最多只能乘2人,用最少的船装所有的人 ,求船数

详细解析均在代码中:(附带算法执行时间)

#include<iostream>
#include<windows.h>
using namespace std;

//n个人(0~n-1),第i个人的体重为wi,每艘船的最大载重均为C,且最多只能乘2人,最少的船装所有的人 
//如果n=0,船也为0
//如果n=1,则船也为1
//如果n>1 先装第一个,然后判断是否刚好装入,
//装完第一个人还有剩余重量就
// 找剩下人中重量小于等于剩余重量的,然后从中找一个最大的,和第一个人一起装入,然后判断下一个人
//第一个人刚刚好装入就
// 判断下一个人
//在此假设所有人的重量均不超过最大装载重量即wi<=C
int findMaxRest(int w[],int low,int high,int restC){
    int t[high+1]={0},index=-1;
    //	cout<<restC<<"-----------restC"<<endl; 
    //	找到重量小于等于restC 的重量 
    for(int i=low;i<=high;i++){
        if(w[i]<=restC){
            t[i]=w[i];
            //			cout<<"t[]"<<t[i]<<endl;
        }
    }
    int maxRest=0;
    for(int i=low;i<=high;i++){
        if(t[i]!=0){
            maxRest=t[i];
            break;
        }
    }
    //	cout<<maxRest<<"初始--------maxRest"<<endl ;
    //	找出 小于等于restC的重量 中最大的 
    for(int i=low;i<=high;i++){
        if(t[i]>=maxRest){
            maxRest=t[i];
            index=i;
        }
    }
    //	cout<<maxRest<<"最后--------maxRest"<<endl ;
    //	返回下标 
    return index;
}

void solve(int w[],int low,int high,int C,int count,int &sum){
    // 0个人
    if(high-low<0){
        sum+=0;
    }
        // 一个人
    else if(low==high){
        if(w[low]!=0){
            sum+=1;
        }	
    }
        // 一个人以上
    else{
        // 如果装下后还有剩余
        if(w[low]<C){
            if(w[low]<=0){
                // 已经装入,考虑下一个 
                solve(w,low+1,high,C,count,sum);
            }else{
                // 还未装入,现在装进,开始找寻剩下人中
                // 重量小于等于C-刚刚装入那个人的重量中的最大值
                // 2,3,4,5  C=7 那么装入第一个2,就找剩下的3,4,5中<=7-2即3,4,5中<=5的
                // 3,4,5均<=5,找出他们当中最大的,5,这样2+5刚刚好等于7,充分装载
                count+=1;
                if(count==2){
                    int restC=C-w[low];
                    w[low]=0;
                    // 找到剩余人中重量<=restC,最大的 
                    int index=findMaxRest(w,low+1,high,restC);
                    // cout<<"----------index="<<index<<endl; 
                    if(index!=-1){
                        w[index]=0;
                    }
                    //	装满一艘船 
                    sum+=1;
                    //	开始判断下一个人的重量
                    solve(w,low+1,high,C,1,sum);
                }else if(count>2){
                    solve(w,low+1,high,C,1,sum); 
                }
            }
        }
            // 如果刚刚好装下,那就开始判断下一个人
        else if(w[low]==C){
            sum++;
            solve(w,low+1,high,C,1,sum);
        }
        //		else if(w[low]>C){
        //			重新装入一艘船 
        //			cout<<"重新装入一艘船"<<endl; 
        //			solve(w,low,high,C,1,sum);
        //		}
    }
} 
int main(){
    _LARGE_INTEGER time_start;	//开始时间
    _LARGE_INTEGER time_over;	//结束时间
    double dqFreq;		//计时器频率
    LARGE_INTEGER f;	//计时器频率
    QueryPerformanceFrequency(&f);
    dqFreq = (double)f.QuadPart;
    //------------
    int n,sum=0,C;
    cout<<"请输入人数:";
    cin>>n;
    cout<<"请输入船的最大载重量:";
    cin>>C; 
    int w[n];
    cout<<"请输入每个人的重量:";
    for(int i=0;i<n;i++){
        cin>>w[i];
    }
    QueryPerformanceCounter(&time_start);	//计时开始
    solve(w,0,n-1,C,1,sum);
    QueryPerformanceCounter(&time_over);	//计时结束
    cout<<"至少需要"<<sum<<"艘船"<<endl;
    cout << "所用时间为" << 1000000 * (time_over.QuadPart - time_start.QuadPart) / dqFreq << "微秒" << endl;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: {70, 80, 60, 50, 30, 20, 10}; 最大载重量 c = 100) 这是一道经典的贪心算法问题,可以采用贪心策略来解决。 首先将人按照体重从小到大排序,然后从体重最轻的人开始,依次选择与其体重最重的人一起乘,直到不能再加入更多的人或者所有人都已经乘。 具体实现可以使用双指针的方法,即设置左右两个指针,分别指向体重最轻的人和体重最重的人,然后不断移动指针,直到所有人都已经乘。 代码实现如下: int n = 7; int w[] = {70, 80, 60, 50, 30, 20, 10}; int c = 100; sort(w, w + n); // 将人按照体重从小到大排序 int ans = ; // 记录的数量 int left = , right = n - 1; // 左右指针 while (left <= right) { if (w[left] + w[right] <= c) { // 如果可以一起乘 left++; // 左指针右移 right--; // 右指针左移 } else { // 如果不能一起乘 right--; // 右指针左移 } ans++; // 的数量加一 } cout << ans << endl; // 输出最少需要的的数量 输出结果为 4,即最少需要 4 艘才能装载所有人。 ### 回答2: 要求用最少来装载所有人,首先我们需要确定每艘最大载重量。由于最多只能乘两个人,因此我们可以将 n 个人体重从小到大排序,然后从体重最轻的人开始,搭配体重最重的人,作为一组上,如果这组人的体重和超过了最大载重量 c,则不能上,需要找到下一组最大的可以上的人。然后再按照同样的方式搭配下一组人。 接下来我们考虑如何用程序实现这个问题。我们可以使用贪心算法,先将人的体重排序,然后从头开始遍历,不断选择最轻的可以上的人和最重的可以上的人,直到没有人可以上为止。 具体实现如下: 1. 定义一个列表 w 存储每个人体重,并将它们从小到大排序。 2. 定义一个变量 boats 表示使用的数,初始值为 0。 3. 定义变量 i 和 j 分别表示轻重两个指针的位置,初始值均为 0。 4. 循环遍历 n 次(即遍历所有人),每次循环判断: - 如果 i >= j,则说明已经没有可以上的人,退出循环。 - 如果 w[i] + w[j] <= c,则将这两个人放在同一艘船上,并将 i 和 j 分别加 1。 - 如果 w[i] + w[j] > c,则不能将这两个人放在同一艘船上,只能体重较重的人单独放在一艘船上,并将 j 减 1。 - 每次放人时,boats 加 1。 5. 输出 boats 的值,即使用的数。 完整代码如下: ``` w = [60, 70, 80, 90, 100, 110, 120] # 七个人体重 w.sort() # 排序 n = len(w) # 人数 c = 150 # 最大载重量 i, j = 0, n - 1 # 轻重指针 boats = 0 # 使用的数 while i <= j: if i == j: boats += 1 break elif w[i] + w[j] <= c: i += 1 j -= 1 boats += 1 else: j -= 1 boats += 1 print("使用的数为:", boats) ``` 运行结果为 4,即需要使用 4 艘才能装载所有人。 ### 回答3: 这道题是一个很经典的贪心算法问题,可以使用贪心的思想,寻找最优解。 首先,两个人体重总和一定要小于等于最大载重量c,因此,我们需要将人按体重从小到大排序。可以使用快速排序等方式。 接着,我们从最轻的人开始,选择和他体重最大的人一起乘出发。比如说,第一个人体重为w[0],那么我们在剩余的人中选择体重最大的人w[i],使得w[0]+w[i]<=c,一起乘出发。假如没有符合条件的人,那么第一个人就要单独乘出发。然后,我们在剩余的人中重复以上步骤,直到所有人都乘完为止。 在这个过程中,我们要注意的是,每当选择一个人,就需要从剩余的人中删除这个人,因为只能乘两个人。另外,如果只有一个人剩余,那么这个人必须单独乘出发。 这样,我们就可以用最少,装载所有人。 具体实现可以参考以下代码: ```python def boat(n, c, w): w.sort() # 将人按体重从小到大排序 i, j = 0, n - 1 # 设置头尾指针 count = 0 # 记录的数量 while i <= j: if w[i] + w[j] <= c: # 选取体重最大的两个人一起上 i += 1 j -= 1 else: # 如果无法同时上只能选择体重大的人单独上 j -= 1 count += 1 return count n = 7 c = 12 w = [1, 2, 5, 6, 7, 8, 9] print(boat(n, c, w)) # 输出结果为3 ``` 以上代码的时间复杂度为O(nlogn),主要是排序的时间复杂度。在实际应用中,还可以采用其他排序算法来提高效率,比如说桶排序等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值