数组分割

题目概述:有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。假设数组A[1..2N]所有元素的和是SUM。模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合。显然:S(k, 1) = {A[i] | 1<= i <= k}S(k, k) = {A[1]+A[2]+…+A[k]}S(k, i) = S(k-1, i) U {A[k] + x | x属于S(k-1, i-1) }按照这个递推公式来计算,最后找出集合S(2N, N)中与SUM最接近的那个和,这便是答案。这个算法的时间复杂度是O(2^N).
#include<iostream>
using namespace std;
int data[10]={1,5,7,8,9,6,3,11,20,17};
int main()
{
    int Sum=0;
    for(int i=0;i<10;i++)
        Sum+=data[i];

    int media[11][6][87/2+2];
    for(int j=0;j<=5;j++)
      for(int i=0;i<=10;i++)
            for(int k=Sum/2;k>=0;k--)
                media[i][j][k]=0;
    for(int j=1;j<=5;j++)
    {
        for(int i=1;i<=10;i++)
          for(int k=data[i-1];k<=Sum/2+1;k++)
            {
                if(0==j)
                    media[i][j][k]=data[i-1];
                else
                {
                    if(media[i-1][j][k]>=media[i-1][j-1][k-data[i-1]]+data[i-1])
                        media[i][j][k]=media[i-1][j][k];
                    else
                        media[i][j][k]=media[i-1][j-1][k-data[i-1]]+data[i-1];

                }
                //  cout<<"(i,j,k)("<<i<<" "<<j<<" "<<k<<")"<<media[i][j][k]<<endl;
            }
      int a;
    //  cin>>a;
    }
    int su=media[10][5][87/2];
    cout<<media[10][5][43]<<" "<<media[9][4][26]<<endl;
    for(int j=5;0<j;)
        for(int i=10;i>0;i--)
        {
         //   cout<<i<<":"<<j<<"       ";
          //  cout<<media[i][j][su]<<" "<<media[i-1][j-1][su-data[i-1]]+data[i-1]<<endl;
            if(media[i][j][su]==media[i-1][j-1][su-data[i-1]]+data[i-1])
            {

                cout<<data[i-1]<<"**";
                su=su-data[i-1];
                j--;
                //cout<<i<<" "<<j<<endl;
            }
        }

    cout<<media[9][4][87/2]<<endl;


    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值