日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数组分割

發布時間:2024/9/30 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数组分割 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有一個元素個數為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. 如果是任意的整數,例如,可能出現負數。’

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;}


總結

以上是生活随笔為你收集整理的数组分割的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。