[算法提高] 分割项链
资源限制
时间限制: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;
}
初次写题解,还希望大神们能够支持!!!