蓝桥杯 [算法提高ADV-381] 分割项链 题解

[算法提高] 分割项链

资源限制
时间限制:1.0s 内存限制:256.0MB


问题描述

  两个强盗刚刚抢到一条十分珍贵的珍珠项链,正在考虑如何分赃。由于他们不想破坏项链的美观,所以只想把项链分成两条连续的珍珠链。然而亲兄弟明算账,他们不希望因为分赃不均导致不必要的麻烦,所以他们希望两条珍珠链的重量尽量接近。于是他们找到了你,希望让你帮忙分赃。
  我们认为珍珠项链是由n颗不同的珍珠组成的,我们可以通过称重,分别称出每颗珍珠的重量(我们忽略连接珍珠的“链”的重量)。你要求的是每个人至少能得到多重的珍珠(即分赃少的那个人能得到多重的珍珠)。
  



输入格式

   第一行一个整数n,表示这个珍珠项链有多少颗珍珠。第二行n个整数,顺时针给出每颗珍珠的重量wi。(你要注意的是,第一课珍珠和最后一颗珍珠是相连的)
  

输出格式

  一个整数,表示分赃少的那个人能得到多重的珍珠。
  

样例输入

7
1 2 3 4 3 2 1


样例输出

7


数据规模和约定

对于30%的数据,n<=200;

  对于60%的数据,n<=2000;

  对于100%的数据,n<=50000,1<=wi<=1000

题意:
本题大概的意思就是说,有一串项链,有n颗珍珠,每个珍珠的重量不一定相同,把他们分给两个人,并且需要两个人分赃的差距最小,输出分赃得少的那一个人。


思路:

这里我就用数组a[ ]存珍珠,直接从第一个珍珠开始加,加到重量(sum1)大于总珍珠重量(sum)时停止,这里我们会用到L,R分别表示数据角标,下一次比较就先减去a[L],然后再判断当前的sum1是否大于sum/2,
如果大于,就进行更新ans,总循环次数n次,下面就开始看代码吧.

60%AC代码:

#include <bits/stdc++.h>
using namespace std;
int a[500005],sum1,sum2,min_=9999999,sum,t=1,ans,n;//t代表起始角标位置
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	int k=n;
	while(k--){
		sum1=0,sum2=0;
		int i=t;//申请i是为了不影响下一次角标位置
		do{//累加sum1
			sum1+=a[i++];
			if(i==n+1){
				i=1;
			}
		}while(sum1<sum/2);
		t++;//角标++
		sum2=sum-sum1;
		if(min_>abs(sum2-sum1)){
			min_=abs(sum2-sum1);
			if(sum2>=sum1){//满足条件更新ans
				ans=sum1;
			}else{
				ans=sum2;
			}	
		}

		sum1=0,sum2=0;	
	}
	cout<<ans;
	return 0;
}

100%AC代码:

//这一次用到了L,R,能够减少sum1累加的次数,解决了超时的问题
//sum1就是a[L]+......+a[R]
//每一次的开始先减去a[L],再判断当前sum1是否大于sum/2,不大于就加a[R+1],往后面的数据加,知道大于为止
#include <bits/stdc++.h>
using namespace std;
int a[500005],sum1,sum2,min_=9999999,sum,ans,n,L=0,R=1;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	int k=n;
	while(k--){
		if(L==n+1){
				L=1;
		}
		sum1=sum1-a[L++];
		while(sum1<sum/2){
			sum1+=a[R++];
			if(R==n+1){
				R=1;
			}
		}
		sum2=sum-sum1;
		if(min_>abs(sum2-sum1)){
			min_=abs(sum2-sum1);
			if(sum2>=sum1){
				ans=sum1;
			}else{
				ans=sum2;
			}	
		}
	}
	cout<<ans;
	return 0;
}

初次写题解,还希望大神们能够支持!!!

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值