数组分割
有一個元素個數為2n的數組a,找出這樣數量相等(均為n個元素)的兩個子數組a1,a2, 使a1中所有元素的和sum1與a2中所有元素的和sum2的差值最小,即|sum1-sum2|最小
1. 如果是正整數數組,可以用背包的思想,進行動態規劃
可以把問題轉化為找到一個n個元素的子數組,使其和最接近于sum/2, 其中sum是數組a的元素之和。
f[v][s] v表示放入v個元素,s表示這v個元素之和。f[v][s] = 1表示,方案可行;0表示,方案不可行。
int segArray(int *a, int n) {int len = n/2;vector<vector<int> > f(len);int sum = 0;for (int i = 0; i < n; ++i)sum += a[i];int S = sum/2;for (int i = 0; i < len ; ++i)f[i].resize(S,0);f[0][0] = 1;for (int i = 0; i < n; ++i) {for (int v = min(len,i+1); v >=1; --v) {for (int s = a[i] ; s <= S; ++s) {if (f[v-1][s-a[i]])f[v][s] = 1;}}}for (int i = S; i >=0; --i)if (f[len][i])return i; }
2. 如果是任意的整數,例如,可能出現負數?!?/p>
http://www.cnblogs.com/nanduo/archive/2009/06/29/1513035.html
/*
?? ?有兩個數組a,b,大小都為n,數組元素的值任意整形數,無序;
?? ?要求:通過交換a,b中的元素,使[數組a元素的和]與[數組b元素的和]之間的差最小。
*/
/*
?? ?求解思路:
?? ?當前數組a和數組b的和之差為
?? ?A = sum(a) - sum(b)
?? ?a的第i個元素和b的第j個元素交換后,a和b的和之差為
?? ?A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
?????????? = sum(a) - sum(b) - 2 (a[i] - b[j])
?????????? = A - 2 (a[i] - b[j])
(主要看這個式子,A>0, 則a[i]-b[j]在0~~A之間,當越接近A/2時,差異就越小)
?? ?設x = a[i] - b[j]
?? ?|A| - |A'| = |A| - |A-2x|
?? ?假設A > 0,
?? ?當x 在 (0,A)之間時,做這樣的交換才能使得交換后的a和b的和之差變小,x越接近A/2效果越好,
?? ?如果找不到在(0,A)之間的x,則當前的a和b就是答案。
?? ?所以算法大概如下:
?? ?在a和b中尋找使得x在(0,A)之間并且最接近A/2的i和j,交換相應的i和j元素,重新計算A后,重復前面的步驟直至找不到(0,A)之間的x為止。
*/
int test(float a[], float b[], int n){float sumA, sumB; //sumA為數組a總和,sumB為數組b總和float sum_diff, num_diff; //sum_diff為a,b總和差, num_diff為a,b中各選的兩個數之差float temp1, temp2; //temp1為 每輪sum_diff/2, temp2為每輪所選兩個數之差于temp1最接近的那個int i, j;float temp; //用于對調a,b間數int tempi, tempj; //每輪所選兩個數之差于temp1最接近的那組數unsigned int flag_sum = 0, flag_num = 0; //flag_sum為1, sumA大于sumB; flag_num為1, 此輪存在兩個數之差小于sum_diffwhile(1){//算出a,b數組和sumA = 0;sumB = 0;for(i=0;i < n;i++){sumA += a[i];sumB += b[i];}if(sumA >= sumB){sum_diff = sumA - sumB;flag_sum = 1;}elsesum_diff = sumB - sumA; temp1 = sum_diff/2;temp2 = temp1;tempi = 0;tempj = 0; //找出a,b間差值最接近sum_diff/2的那一對數if(flag_sum == 1){ //sumA > sumBfor(i=0; i < n; i++)for(j=0; j < n; j++)if(a[i] > b[j]){num_diff = a[i] - b[j];if(num_diff < sum_diff){flag_num =1;if(num_diff >= temp1){if(num_diff-temp1 < temp2){temp2 = num_diff-temp1;tempi = i;tempj = j;}}else{if(temp1 - num_diff < temp2){temp2 = temp1 - num_diff;tempi = i;tempj = j;}}}}}else{for(i=0; i < n; i++)for(j=0; j < n; j++)if(a[i] < b[j]){num_diff = b[j] - a[i];if(num_diff < sum_diff){flag_num =1;if(num_diff >= temp1){if(num_diff-temp1 < temp2){temp2 = num_diff-temp1;tempi = i;tempj = j;}}else{if(temp1 - num_diff < temp2){temp2 = temp1 - num_diff;tempi = i;tempj = j;}}}}}if(flag_num == 0)break;temp = a[tempi];a[tempi] = b[tempj];b[tempj] = temp;flag_num = 0;flag_sum = 0;}for(i=0; i < n;i++)printf("%f\t",a[i]);printf("\n");for(i=0; i < n;i++)printf("%f\t",b[i]);printf("\n"); return 0;}int main(int argc, char *argv[]){float a[3] = {4,5,12};float b[3] = {1,2,3};test(a, b, 3);return 0;}
總結
- 上一篇: 不用额外空间,链接二叉树同一层的每个no
- 下一篇: Rearrange an array o