数列划分问题

整数数列 a,先输入 a 的元素个数 n,再输入整数数列 a 的各元素 (数组 a 中元素个数不超过 10 个),寻找是否有这样一种划分: 将 a 中元素分为两组,使得这两组中的元素之和相等。若可以找到,输出 True, 并写出一种划分 (输出格式见样例); 若不能,输出 False。
样例 1:
        输入:7

                1 2 3 4 5 6 9
        输出:True
                 (6.9)

                 (1,2,3,4,5)
样例 2:
        输入:3

                 1 3 5
        输出:False

 

题目介绍:需要对一个输入的数组尝试划分。这种题目可以采取动态规划方法计算。

整体思路:计算出整个数列各项和(sum)。如果是奇数,则不可能平分,直接输出“False”;如果是偶数,则要凑出一个子列,使其各项和为sum的一半(half)。

细节方法:假定输入的数列升序排列(若不是,可以先排序)。选定最后一位(last),向前检索,根据现有求和(temp)和目标和(half)的大小来决定是否加入正在检索的一位。整个数列检索后,若成功,输出“True”和划分方式;若不成功,前移最后一位last所在位置,再次检索。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int a[15];//输入的数列
int l[15];//其中一个划分部分
int r[15];//剩下的部分

int main(void) {
 int N;//数列里数的个数
 int n = 0;//第一个部分数的个数
 int m = 0;//第二个部分数的个数
 int key = 0;//判断是否可行
 int sum = 0;//数列求和
 int half = 0;//求和值得一半
 int temp = 0;//当前求得和值
 cin >> N;
 for (int i = 0; i < N; i++) {
  cin >> a[i];
  sum += a[i];
 }//按照题目要求输入
 if (sum % 2 != 0)
  key = -1;//如果数列求和,和值是奇数,无论如何不能划分
 else {
  half = sum / 2;
  //假定所有的数字按照升序排列;如果不是,那就自己给他排一下
  for (int j = N - 1; j >= 1; j--) {
   temp = a[j];//制定一个最后一位,假定划分中包含这个最后一位,检验是否可行
   for (int k = j - 1; k >= 0; k--) {
    if (temp == half) {
     key = 1;
     break;//划分成功,结束
    }
    else if (temp < half) {
     temp += a[k];
     l[n] = k;
     n++;
     //当前值比和值一半小,那就加上这一位的数字,并把这个数字的位置记录在了l[n]划分部分里;
    }
    else {
     if (temp == a[j])
      break;//说明最后一位大于和值的一半,不可能能够划分;
     else {
      temp -= a[k + 1];
      temp += a[k];
      n--;
      l[n] = k;
      n++;
     }
     //当前值比和值一半大,那就减去上一个数字,加上当前位置数字,并把这个数字的位置替换上一个数字的位置
    }
   }
   if (key == 1) {
    l[n] = j;
    break;
    //如果成功,记录下选定的最后一位的位置
   }
  }
 }
 if (key == 1) {
  int p = 0;
  for (int i = 0; i < N; i++) {
   for (int j = 0; j <= n; j ++ ) {
    if (i != l[j]) {
     continue;
    }
    else {
     p = -1;
     break;
    }
   }
   if (p == 0) {
    r[m] = i;
    m++;
   }
   //划分成功,则把了l[n]这一部分中没有的数字位置记录给r[m];
  }
  cout << "True" << "\n";
  cout << '(';
  for (int i = n - 1; i >= 0; i--) {
   cout << a[l[i]];
   cout << ',';
  }
  cout << a[l[n]] << ')' << "\n";
  cout << '(';
  for (int i = 0; i < m - 1; i++) {
   cout << a[r[i]];
   cout << ',';
  }
  cout << a[r[m - 1]] << ')';
 }
 else
  cout << "False";
 return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值