• 两个序列最大子集公共和问题


    前几天听同学说起这样一个问题,说有两堆物品,分别从两堆物品中挑出一些物品,使这些物品重量之和相同,要求使重量之和最大。我把这个问题抽象出来后是这样子:有两个序列,从两个序列中各选出一些元素组成子序列,使这两个子序列的和相等,要求使子序列的和最大。

    我设计的算法如下:

    1.两个序列选择子序列按照0-1方式生成解空间。所以按回溯方式遍历解空间。

    2.要实现高效得考虑贪心性。

    3.序列和小的序列的和很大概率上就是两个序列的最大子集公共和。

    4.序列和小的序列做基础。

    5.对原序列排序,如果较密集,小序列用降序排列。如果两个序列和的差较大,大序列用升序排列。

      1  #include "stdafx.h"
      2  #include <iostream>
      3  using std::cout;
      4   
      5  const int VALUE=1000;
      6   
      7  /*为方便,用全局变量做实验*/
      8  
      9   int cSumA=0;//当前过程中A的被检验的和
     10   int cSumB=0;//当前过程中B的被检验的和
     11   int rSumA=0;//当前过程中A中剩余元素的总和
     12   int rSumB=0;//当前过程中B中剩余元素的总和
     13   
     14   int sumA=0;//A序列的和
     15   int sumB=0;//B序列的和
     16   int comSum=0;//当前过程中记录的最优子集公共和
     17   
     18   const int aSize=10;
     19   const int bSize=10;
     20   int A[aSize+1]={0, 221,411,345,926,451,1425,882, 1213,453,782};
     21   int B[bSize+1]={0,45,664,1121,551,144,489,841,1120,356,1245};
     22   int *a;
     23   int *b;
     24   int tempsubA[aSize+1]={0};
     25   int tempsubB[bSize+1]={0};
     26   
     27   int resultsubA[aSize+1]={0};
     28   int resultsubB[bSize+1]={0};
     29   
     30   void BacktrackSumA(int i);    //回溯遍历法
     31   void BacktrackSumB(int i);
     32  
     33  //快速排序的patition,Ds为降序 
     34   int patitionDs( int arr[],int left , int right )
     35   {
     36       int pivot=arr[left];
     37       while(left<right)
     38       {
     39           while(left<right&&arr[right]<=pivot)
     40               right--;
     41           arr[left]=arr[right];
     42           while(left<right&&arr[left]>=pivot)
     43               left++;
     44           arr[right]=arr[left];
     45       }
     46       arr[left]=pivot;
     47       return left;
     48   }
     49   //快速排序,降序
     50   void quickSortDs( int arr[], int left, int right )
     51   {
     52       int pivot;
     53       if(left<right)
     54       {
     55           pivot=patitionDs( arr,left,right);
     56           quickSortDs( arr, left, pivot-1);
     57           quickSortDs(arr, pivot+1,right);
     58       }
     59   }
     60   
     61   int patitionAs( int arr[],int left , int right )
     62   {
     63       int pivot=arr[left];
     64       while(left<right)
     65       {
     66           while(left<right&&arr[right]>=pivot)
     67               right--;
     68           arr[left]=arr[right];
     69           while(left<right&&arr[left]<=pivot)
     70               left++;
     71           arr[right]=arr[left];
     72       }
     73       arr[left]=pivot;
     74       return left;
     75   }
     76   
     77   void quickSortAs( int arr[], int left, int right )
     78   {
     79       int pivot;
     80       if(left<right)
     81       {
     82           pivot=patitionAs( arr,left,right);
     83           quickSortAs( arr, left, pivot-1);
     84           quickSortAs(arr, pivot+1,right);
     85       }
     86   }
     87   
     88  //获取A序列的和。
     89   void getSumA()
     90   {
     91       for(int i=1;i<=aSize;i++)
     92           sumA=rSumA+=A[i];
     93   }
     94   
     95   void getSumB()
     96   {
     97       for(int i=1;i<=bSize;i++)
     98           sumB=rSumB+=B[i];
     99   }
    100   
    101  //回溯法遍历A的解空间
    102   void BacktrackSumA(int i)
    103   {
    104       if(i>aSize)
    105       {   
       if(cSumA>comSum && cSumA<=sumB) 106 {
       rSumB=sumB; 107 BacktrackSumB(1); 108 int f=0; 109 } 110 return; 111 } 112 if(cSumA+rSumA>comSum) 113 { 114 rSumA-=a[i]; 115 116 cSumA+=a[i]; 117 tempsubA[i]=a[i]; 118 BacktrackSumA(i+1); //系数xi取1 119 tempsubA[i]=0; 120 cSumA-=a[i]; 121 122 BacktrackSumA(i+1); //系数xi取0 123 124 rSumA+=a[i]; 125 } 126 } 127 128 void BacktrackSumB( int i) 129 { 130 if(i>bSize) 131 return; 132 if(cSumB+rSumB>=cSumA) 133 { 134 rSumB-=b[i]; 135 if(cSumB+b[i]==cSumA) 136 { 137 for(int j=0;j<=aSize;j++) 138 resultsubA[j]=tempsubA[j]; 139 for(int j=0;j<bSize;j++) 140 resultsubB[j]=tempsubB[j]; 141 resultsubB[i]=b[i]; 142 comSum=cSumA; 143 return; 144 } 145 if(cSumB+b[i]<cSumA) //系数yi取1 146 { 147 cSumB+=b[i]; 148 tempsubB[i]=b[i]; 149 BacktrackSumB(i+1); 150 cSumB-=b[i]; 151 tempsubB[i]=0; 152 } 153 BacktrackSumB(i+1); //系数yi取0 154 rSumB+=b[i]; 155 } 156 } 157 158 int _tmain(int argc, _TCHAR* argv[]) 159 { 160 getSumA(); 161 getSumB(); 162 if(sumA<sumB) 163 { 164 a=A; 165 b=B; 166 } 167 else 168 { 169 int tem=sumA; 170 sumA=rSumA=sumB; 171 sumB=rSumB=tem; 172 a=B; 173 b=A; 174 } 175 if(sumB-sumA>VALUE) //用VALUE做阀值,以确定用哪种排序 176 { 177 quickSortAs( a, 1,aSize); 178 quickSortAs( b, 1,bSize); 179 } 180 else 181 { 182 quickSortDs( a, 1,aSize); 183 quickSortDs( b, 1,bSize); 184 } 185 BacktrackSumA(1); 186 cout<<comSum; 187 188 getchar(); 189 return 0; 190 }
  • 相关阅读:
    2019沈阳网路赛 D. Fish eating fruit (点分治)
    2019南京网路赛 A.The beautiful values of the palace (主席树)
    洛谷 P2634 [国家集训队]聪聪可可(点分治)
    AcWing252 树 (点分治模板题)
    点分治模板 (洛谷 P3806)
    2020牛客寒假算法基础集训营2 J-求函数(线段树维护矩阵乘法)
    七夕祭(贪心+中位数)
    数据结构-集合
    数据结构-广义表
    数据结构-稀疏矩阵
  • 原文地址:https://www.cnblogs.com/kevinGaoblog/p/2489362.html
Copyright © 2020-2023  润新知