题目描述:
为了排出完美的拍照队形,班长想出了一种方法:他让全班人分成了n组,从左到右排开,每一组站在一起,第i组有ai个人。但是当他仔细观察时,发现他设计的分组方案并不对称。不对称就产生了很多问题,照片不好看还是其次的,最重要的一点是会影响公平性,最终影响班级团结,导致同学间失和。为了安抚烦躁的人群,班长必须用尽量简洁的方法来调整分组。由于场面混乱,他每次只能把相邻的两组人合为一组。他想知道,他最少需要多少次合并操作,才能让分组方案在数量上对称?
例如:一开始分了7组,人数分别为:2 5 3 2 8 1 1。
让第二和第三组合并,得到:2 8 2 8 1 1
再让最后两组合并,得到:2 8 2 8 2
这样只需要两次操作,在数量上就达到了对称。
输入:
第一行 n
第二行 n个数,a1到an。
输出
一个数,最少操作数。
数据范围:
分数 n
30 10
30 1000
40 10^6
ai为正整数,总和小于等于10^9
时间限制:1s
样例数据:
输入 输出
3
1 2 3 1
5
1 2 4 6 1 1
4
1 4 3 2 2
样例解释:
1 2 3 -> 3 3
1 2 4 6 1 -> 1 6 6 1
1 4 3 2 -> 5 3 2 -> 5 5
解法:本题是个明显贪心题,用从头到尾和从尾到头的方法。设置两个指针l和r,l从左往右,r从右往左,即可得出a[l+1]+=a[l]; a[r-1]+=a[r];这两个算式!核心√。直到a[l]==a[r]时才停止。或者是l==r时停止。(备注:a[l]>a[r]时,a[r]做运算,反之则a[l]做运算,当你不知道什么时候对a[l]或a[r]做运算,最好用函数。简单递归即可)
get代码如下:
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> typedef long long ll; using namespace std; int a[1000008],n,ans,l,r; ll sum; void fun(int x,int y){ if(a[x]==a[y]){ l=x; r=y; return;} if(a[x]>a[y]){ a[y-1]+=a[y]; sum++; fun(x,y-1); return; } if(a[x]<a[y]){ a[x+1]+=a[x]; sum++; fun(x+1,y); return; } return; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); l=1; r=n; while(l<r){ if(l==r) break; if(a[l]==a[r]) { l++; r--; continue; } fun(l,r); } cout<<sum; return 0; }