1 条题解

  • 1
    @ 2025-11-12 21:58:16

    一开始,我试图通过贪心策略确定每次带奶牛的最大数量(maxx),然后固定每次带maxx头奶牛过河。

    也就是

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,mi,a[2501],maxx,t;
    bool b;
    int main(){
    	cin>>n>>m;
    	a[0]=m;
    	for(int i=1;i<=n;i++){
    		cin>>mi;
    		a[i]=a[i-1]+mi;
    		if(a[i]>(a[i-1]+a[1]+m)&&b==0){
    			b=1;
    			maxx=i-1;
    		}
    	}
    	if(b==0){
    		maxx=n;
    	}
    	while(n>0){
    		if(n>=maxx){
    			t+=a[maxx];
    			n-=maxx;
    		}
    		else{
    			t+=a[n];
    			n=0;
    		}
    		if(n!=0){
    			t+=m;
    		}
    	}
    	cout<<t;
    	return 0;
    }
    

    但是这种方法在某些情况下可能不是最优的,因为它只考虑了带i头奶牛与带i-1头和1头奶牛的对比,而没有考虑其他分配方式(例如带2头和2头可能比带3头和1头更优)。因此,此代码在特定数据下可能无法得到最短时间。

    所以为了解决这个问题,建议使用动态规划(DP)方法。DP方法通过计算所有可能的分段方式,确保找到最短总时间。具体步骤如下:

    1.读取奶牛数量n和独自渡河时间m。

    2.计算数组a,其中a[i]表示带i头奶牛过河所需的时间(包括基础时间m和额外时间)。

    3.初始化DP数组dp,其中dp[i]表示带i头奶牛过河的最短总时间,初始时dp[0] = 0。

    4.对于每个i从1到n,遍历所有可能的j(1到i),计算dp[i] = min(dp[i], dp[i-j] + a[j] + (i-j > 0 ? m : 0))。这表示将i头奶牛分为先带i-j头再带j头,其中如果i-j>0则需要返回时间m。

    5.输出dp[n]。

    也就是

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int n,m;
    	cin>>n>>m;
    	int a[n+1];
    	a[0]=m;
    	for(int i=1;i<=n;i++){
    		int mi;
    		cin>>mi;
    		a[i]=a[i-1]+mi;
    	}
    	int dp[n+1];
    	dp[0]=0;
    	for(int i=1;i<=n;i++){
    		dp[i]=1e9;
    		for(int j=1;j<=i;j++){
    			if(i-j>0){
    				dp[i]=min(dp[i],dp[i-j]+a[j]+m);
    			}else{
    				dp[i]=min(dp[i],dp[i-j]+a[j]);
    			}
    		}
    	}
    	cout<<dp[n];
    	return 0;
    }
    
    • 1

    信息

    ID
    2824
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    76
    已通过
    9
    上传者