首页 > 试题广场 >

小强去春游

[编程题]小强去春游
  • 热度指数:2727 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解
小强作为强班的班长.决定带着包含他在内的个同学去春游.路程走到一半,发现前面有一条河流.且只有一条小船.经过实验后发现,这个小船一次最多只能运送两个人.而且过河的时间是等于两个人中体重较大的那个人的体重.如果只有一个人,那么过河时间就是这个人的体重.现在小强想请你帮他分析如何安排才能在最短时间内使所有人都通过这条河流.小强很懒,他并不想知道具体怎么过河,只要你告诉他最短的时间.

输入描述:
第一行输入一个整数.表示有组测试数据.
每组数据,第一行输入一个整数.表示人数.
接下来一行输入个整数,表示第个人的体重是.





输出描述:
每组测试数据输出一个答案.
示例1

输入

2
4
2 10 12 11
4
2 3 7 8

输出

37
19
人数大于4时,过河时先将最重的两个人渡过去,此时有两种思路,一种是最轻的人走2次,每次带一个。另一种是最轻和次轻先过去,最轻回来,最重和次重坐过去,次轻回来。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,t,a[100005];
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int i,j;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=1; i<=n; i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        ll ans=0;
        while(n>=4)
        {
            ans+=min(a[1]*2+a[n-1]+a[n],a[1]+2*a[2]+a[n]);
            n-=2;
        }
        if(n==3)
            ans+=a[1]+a[2]+a[3];
        else if(n==2)
            ans+=a[2];
        else if(n==1)
            ans+=a[1];
        cout<<ans<<endl;
    }
    return 0;
}



发表于 2021-04-30 12:38:57 回复(7)
剩余人数不少于4的时候,比较如下两种操作方案看哪一种用时更少:
1.最轻的人由重到轻每次带过去一个人然后开船回来(为了和方案2对齐,每次也只运2个人);
2.最轻和次轻的过去,然后最轻的回来让最重的两个过去,次轻的在那边把船再开回来。一共运过去了2个人。
这样一来,人数少于4的时候要么只有最轻的3个人,要么只有最轻的2个人。如果还剩3个人,就让最轻的每次带一个;如果还剩2个人,就直接两个人过河了。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        while(T-- > 0){
            int n = Integer.parseInt(br.readLine());
            String[] params = br.readLine().trim().split(" ");
            int[] weights = new int[n];
            for(int i = 0; i < n; i++) weights[i] = Integer.parseInt(params[i]);
            System.out.println(crossRiver(weights));
        }
    }
    
    private static int crossRiver(int[] weights) {
        Arrays.sort(weights);
        int n = weights.length;
        int totalTime = 0;
        while(n >= 4){
            /* 1.最轻的每次都将船开回来,每次载一个;
               2.最轻的两先过去,最轻的那个开船回来让最重的两个过去,那边轻的再把船开回来
            */
            totalTime += Math.min(weights[0]*2 + weights[n - 2] + weights[n - 1], 
                                  weights[0] + weights[1]*2 + weights[n - 1]);
            n -= 2;
        }
        // 还剩不到4人
        if(n == 3)
            totalTime += weights[0] + weights[1] + weights[2];
        else
            totalTime += weights[1];     // 最轻的两个快速过河
        return totalTime;
    }
}

发表于 2021-07-19 12:04:51 回复(1)

当人数小于3的时候, 均仅有一种最优解
当人数大于3的时候, 最重的两个人有两种过河方法:
假设四个人体重为:
方法一: a和d先过河, 然后a再回来接c, 最后a再把船还回来, 此时需要时间
方法二: a和b先过河, 然后a再回来还船, c和d再过河, 最后b把船还回来, 此时需要时间
一直从这两个方法中抉择, 最后到达人数小于3的情况

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define int long long

void slove() {
    int n; cin >> n; vector<int> a(n);
    for(int &t : a) cin >> t;
    sort(a.begin(), a.end());

    int l = 0, r = n - 1, ans = 0;
    while(r >= 3){
        ans += min(a[0] + a[r] + a[0] + a[r - 1], a[0] + a[1] + a[1] + a[r]);
        r -= 2;
    }
    if(r == 2) ans += a[0] + a[1] + a[2];
    else if ( r == 1) ans += a[1];
    else ans += a[0];

    cout << ans << endl;
}

signed main() {
    int T; cin >> T; while(T--) slove();
}
发表于 2022-03-13 07:53:39 回复(0)
私以为小强不适合当班长,太懒了
发表于 2021-08-11 09:51:48 回复(1)
T = int(input())
for _ in range(T):
    n = int(input())
    nums = [int(i) for i in input().split()]
    nums.sort()
    time_min = 0
    while len(nums) >= 4:
        # 每次送走最重的两个人,按楼主说的比较两种方案的时间较短者
        time_min += min(nums[-1] + nums[-2] + nums[0] * 2, nums[0] + nums[1] * 2 + nums[-1])
        # 送走之后讲最重的两个***出列表
        nums.pop(-1)
        nums.pop(-1)
    if len(nums) == 3:
        time_min += sum(nums)
    elif len(nums) == 2:
        time_min += max(nums)
    print(time_min)
        

发表于 2022-03-02 21:23:41 回复(0)
package main

import (
	"fmt"
	"sort"
)

func main() {
	var t int
	fmt.Scan(&t)
	for i := 0; i < t; i++ {
		var n int
		fmt.Scan(&n)
		nums := make([]int, 0)
		for j := 0; j < n; j++ {
			var ele int
			fmt.Scan(&ele)
			nums = append(nums, ele)
		}
		fmt.Println(guohe(nums, n))
	}
}
func guohe(nums []int, n int) int {
	ans := 0
	sort.Ints(nums)
	for n > 3 {
		ans += min(nums[n-1]+nums[n-2]+2*nums[0], 2*nums[1]+nums[0]+nums[n-1])
		n = n - 2
	}
	if n == 3 {
		ans += nums[2] + nums[0] + nums[1]
	}
	if n == 2 {
		ans += nums[1]
	}
	if n == 1 {
		ans += nums[0]
	}
	return ans
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
为啥超时了。。。。
发表于 2023-03-10 20:41:52 回复(1)
这个题的重点是要找到规律和复杂问题化成子问题?
if __name__ == "__main__":
    n = int(input())
    for i in range(n):
        m = int(input())
        num = list(map(int,input().split()))
        num = sorted(num)
        minTime = 0
        i = m - 1
        while(i >= 3):
            minTime += min(2*num[0]+ num[i] + num[i-1] ,num[i]+2*num[1]+num[0])
            i -= 2
        if i == 2:
            minTime += num[0] + num[1] + num[2]
        elif i == 1:
            minTime += num[1]
        print(minTime)

    


发表于 2022-08-03 21:24:17 回复(0)
#include<bits/stdc++.h>
using namespace std;

int helper(int n, vector<int>& weights){
    //先从小到大排序便于贪心
    if(n == 0) return 0;
    sort(weights.begin(), weights.end());
    //贪心,当人数不小于4时,我们可知一定是先让最重的过去是最优,此时最优解有两种情况:
    //(1)每次都让最轻的分别把最重和次重的运过去,耗时2 * weights[0] + weights[n - 1] + weights[n - 2]
    //(2)第一次先让最轻和次轻过去,最轻回去,最重和次重一起过去,次轻回来,耗时 2*weights[1] + weights[0] + weights[n - 1]
    //故每次取两者最小值即可
    //可知最后留下来的不是最轻的3个人,就是最轻的2个人
    //这时3个人,那就是weights[0] + weights[1] + weights[2];
    //这时2个人,那就是weights[1];
    //最后特殊情况只有1个人不要忘记
    int minTime = 0;
    while(n >= 4){
        minTime += min(2 * weights[0] + weights[n - 1] + weights[n - 2],
                       2 * weights[1] + weights[0] + weights[n - 1]);
        n -= 2;
    }
    if(n == 3){
        minTime += weights[0] + weights[1] + weights[2];
    }
    else if(n == 2) minTime += weights[1];
    else minTime += weights[0];
    return minTime;
}


int main(){
    int times;
    cin >> times;
    while(times-- > 0){
        int n;
        cin >> n;
        vector<int> weights(n);
        for(int i = 0; i < n; i++){
            cin >> weights[i];
        }
        cout << helper(n, weights) << endl;
    }
}
发表于 2022-03-12 19:26:08 回复(0)
请问一下大佬们为什么我以下代码过了题目给的例子,但提交实例一个都没对啊?感谢感谢
T=int(input())
for i in range(T):
    n=int(input())
    a=list(map(int,input().split()))
    if n<3:
        print(max(a))
        continue
    a.sort()
    temx=0
    for j in range(n):
        temx=temx+a[j]
    max1=temx+(n-3)*a[0]
    max2=temx+2*a[1]-a[n-2]+(n-4)*a[0]
    if max1<=max2:
        print(max1)
    else:
        print(max2)


发表于 2022-01-13 00:17:41 回复(1)
int main()
{
    int T;
    int n; 
    int a[1000000];
    int time = 0;
    int count = 0;
    int temp_n = 0;
    int j;
    scanf("%d\n",&T);
    for (int i=0; i<T; i++)
    {
        scanf("%d\n",&n);
        for (j=0; j<n; j++)
        {
            scanf("&d",&a[j]);
        }
请教下为什么a[]里无法获得输入参数呀
发表于 2021-12-04 14:26:48 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>

int main(){
    int n = 0;
    std::ios::sync_with_stdio(0),std::cin.tie(0);
    std::cin >>n;
    for(int i=0;i<n;i++){
        int length = 0;
        std::vector<int>temp_ans;
        std::cin >> length;
        for(int i=0;i<length;i++){
            int temp = 0;
            std::cin>>temp;
            temp_ans.push_back(temp);
        }
        std::sort(temp_ans.begin(),temp_ans.end());
        int ans = 0;
        while(length>=4){
            int plan1 = temp_ans[0]*2 + temp_ans[length-2]+temp_ans[length-1];
            int plan2 = temp_ans[0]+temp_ans[1]*2+temp_ans[length-1];
            ans += std::min(plan1,plan2);
            length-=2;
        }
        if(length==3){
            ans+=temp_ans[0]+temp_ans[1]+temp_ans[2];
        }
        if(length==2){
            ans+=temp_ans[1];
        }
        if(length==1){
            ans+=temp_ans[0];
        }
        std::cout<< ans << std::endl;
    }
}


发表于 2021-08-19 22:02:12 回复(0)
没搞懂,第一个例子为什么不是12和11一起,取最大的12.再把10跟2一起,取最大的10?然后12+10得22呢
发表于 2021-06-09 10:53:01 回复(2)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int T=scanner.nextInt();
        for(int i=0;i<T;i++){
            int n=scanner.nextInt();
            int[] weights=new int[n]; 
            for(int j=0;j<n;j++){
                weights[j]=scanner.nextInt();
            }
            int sum=0;
            Arrays.sort(weights);
            for(int j=weights.length-1;j>2;j-=2){
                if(weights[1]*2+weights[0]+weights[j]<weights[0]*2+weights[j-1]+weights[j]){
                    sum+=weights[1]*2+weights[0]+weights[j];
                }
                else{
                    sum+=weights[0]*2+weights[j-1]+weights[j];
                }
            }
            sum+=weights[1];
            if(n%2==1){
                sum+=weights[2]+weights[0];
            }
            System.out.println(sum);
        }
    }
}
发表于 2021-04-28 16:35:46 回复(0)
public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 输入组数
        int T = in.nextInt();
        in.nextLine();
        while (T-- > 0) {
            // 输入人数
            int n = in.nextInt();
            in.nextLine();
            int[] weights = new int[n];
            String[] s = in.nextLine().split(" ");
            for (int i = 0; i < n; i++) {
                weights[i] = Integer.parseInt(s[i]);
            }
            Arrays.sort(weights);
            int res = 0;
            while (n >= 4) {
                // 最小的带最大的过去,然后回来
                int plantOne = weights[n - 1] + weights[0] * 2 + weights[n - 2];
                int plantTwo = weights[1] * 2 + weights[0] + weights[n - 1];
                res += Math.min(plantOne, plantTwo);
                n -= 2;
            }
            if (n == 3) {
                res += weights[0] + weights[1] + weights[2];
            }
            if (n == 2) {
                res += weights[1];
            }
            if (n == 1) {
                res += weights[0];
            }
            System.out.println(res);
        }
    }

发表于 2021-04-28 15:00:56 回复(0)