题目C 前后相加
给定一个序列,长度为N,开始时,上面所有元素为0。你可以对序列作如下两种操作:
1.指定一个整数k (1<=k<=N)和一个非降序列c1, c2,c3,…, ck,(ci非负,1<=i<=k),对序列x的前k个数,令 xi=ci+xi。
2.指定一个整数k (1<=k<=N)和一个非升序列c1, c2,c3,…, ck,(ci非负,1<=i<=k),对序列x的后k 个数,令 x[N-k+i]=ci+x[N-k+i]。
你的目标是将序列x构造为与序列A相等的序列,即 xi=Ai(1<=i<=n),输出最少需要多少此操作,以达成目标。
解题思路:
用连续非升、连续非降,把数列分段。分段的有效段数(需要再次讨论,如有0的段)是最少次数。
具体解法:
获取序列长度及目标序列并存储。若序列从第一个元素向后有连续的0或最后一个元素向前有连续的0,易得这些0无意义,为了方便后续处理,先将这些0标记为-1(因为元素值一定非负,用-1可以表示该元素无意义)。
然后可以开始对序列按照连续非升、连续非降进行分段,分段后的序列存储在二维数组中,一段序列占一个行。算法设计为先从序列头部开始的每一个有意义(非-1)元素向后遍历,遍历到该元素时将该元素存在二维数组中,若大于其后一个元素则说明后一个元素在二维数组中在下一行并跳出本次向后遍历,否则不换行,每成功遍历并存储一个元素就将该元素标记为-1,保证每个元素只遍历一次,然后进行从序列尾部部开始的每一个有意义(非-1)元素向前遍历,具体类似上一步不再赘述。
遍历存储结束后还需要判断一下是否有无意义的0占了二维数组的一行,若有则该行忽略。最后,要求的操作次数即二维数组的有效行数。
运行结果:
#includeusing namespace std; int n ; int * a ,* aa; int ** b; int main(){ cin>>n; a = new int[n]; aa = new int[n]; for(int i = 0 ; i < n ; i++){ cin>>a[i]; aa[i]=a[i]; } // cout<<"a[i]= "; // for(int i = 0 ; i < n ; i++){ // cout<=0){ a[j]=-1; j--; } } // cout<<"na[i]= "; // for(int i = 0 ; i < n ; i++){ // cout<=a[j+1]){ a[j]=-1; m++; k = 0; break; } a[j]=-1; } } for(int j = n-1 ; j >= i ; j--){ if(a[j]!=-1 ){ b[m][k]=a[j]; // cout<<"bm: "< =a[j-1]){ a[j]=-1; m++; k = 0; break; } a[j]=-1; } } } int icount = m; cout< =0 ; m--){ bool bflag = 0; for(k = 0 ; k < n ; k++){ if(b[m][k]!=0) bflag = 1; } if(bflag==0) icount--; } // cout<<"icount= "; cout<



