最大子段和問題-蠻力法、分治法、動態規劃法
蠻力法:
int maxSum1(int a[], int n){ int i; int j; int maxSum = 0; for(i = 0; i < n; i++){ int sum = 0; for(j = i; j < n; j++){ sum += a[j]; if(sum > maxSum){ maxSum = sum; } } } return maxSum; }
分治法:
int maxSum2(int left, int right, int a[]){ int center , i; int sum, left_sum, right_sum; int left_max, right_max; if(left == right) return a[left] ; else{ center = (left + right) / 2; left_sum = maxSum2(left, center, a); right_sum = maxSum2(center+1, right, a); sum = 0; left_max = 0; //求左邊的最大值 for(i = center; i >= left; i--){ sum += a[i]; if(sum > left_max){ left_max = sum; } } sum = 0; right_max = 0; //求右邊的最大值 for(i = center + 1; i <= right; i++){ sum += a[i]; if(sum > right_max){ right_max = sum; } } sum = right_max+ left_max; if(sum < left_sum) sum = left_sum; if(sum < right_sum) sum = right_sum; } return sum ; }
動態規劃法:
void maxSum3(int a[], int n){ int b[n]; int i, j, s = n - 1; int maxSum = 0; b[0] = a[0]; //只有一個數時 最大子段和是其本身 for(i = 1; i < n; i++){ if(b[i - 1] > 0) b[i] = b[i - 1] + a[i]; else{ //前面的值小於0 直接從當前原陣列開始 b[i] = a[i]; } } /* printf("\n\n動態規劃法 列印b陣列:"); for(i = 0; i < n; i++){ printf("%d ", b[i]); } printf("\n"); */ for(j = 0; j < n; j++){ if(b[j] > maxSum){ s = j; maxSum = b[j]; } } printf("\n動態規劃法求出最大子段和為:%d", maxSum); for(i = s-1; i >= 0; i--){ if(b[i] <= 0) break; } printf("\n\n列印最大子段:\n"); for(i = i + 1; i <= s; i++){ printf("%d ", a[i]); } }
完整程式碼:
#include <stdio.h>
#include <stdlib.h>
#define N 10
//判斷是否全為負數
int IsFuShu(int a[], int n){
int i = 0;
for(i = 0; i < n; i++){
if(a[i] > 0)
break;
}
if(i == n)
return -1; //全是負數時
else
return 0; //有正數時
}
//蠻力法
//從第一個數開始,找第一個到最後一個數間最大欄位和;再從第二個數開始
int maxSum1(int a[], int n){
int i;
int j;
int maxSum = 0;
for(i = 0; i < n; i++){
int sum = 0;
for(j = i; j < n; j++){
sum += a[j];
if(sum > maxSum){
maxSum = sum;
}
}
}
return maxSum;
}
//分治法
int maxSum2(int left, int right, int a[]){
int center , i;
int sum, left_sum, right_sum;
int left_max, right_max;
if(left == right)
return a[left] ;
else{
center = (left + right) / 2;
left_sum = maxSum2(left, center, a);
right_sum = maxSum2(center+1, right, a);
sum = 0;
left_max = 0;
//求左邊的最大值
for(i = center; i >= left; i--){
sum += a[i];
if(sum > left_max){
left_max = sum;
}
}
sum = 0;
right_max = 0;
//求右邊的最大值
for(i = center + 1; i <= right; i++){
sum += a[i];
if(sum > right_max){
right_max = sum;
}
}
sum = right_max+ left_max;
if(sum < left_sum)
sum = left_sum;
if(sum < right_sum)
sum = right_sum;
}
return sum ;
}
//動態
void maxSum3(int a[], int n){
int b[n];
int i, j, s = n - 1;
int maxSum = 0;
b[0] = a[0]; //只有一個數時 最大子段和是其本身
for(i = 1; i < n; i++){
if(b[i - 1] > 0)
b[i] = b[i - 1] + a[i];
else{ //前面的值小於0 直接從當前原陣列開始
b[i] = a[i];
}
}
/* printf("\n\n動態規劃法 列印b陣列:");
for(i = 0; i < n; i++){
printf("%d ", b[i]);
}
printf("\n");
*/
for(j = 0; j < n; j++){
if(b[j] > maxSum){
s = j;
maxSum = b[j];
}
}
printf("\n動態規劃法求出最大子段和為:%d", maxSum);
for(i = s-1; i >= 0; i--){
if(b[i] <= 0)
break;
}
printf("\n\n列印最大子段:\n");
for(i = i + 1; i <= s; i++){
printf("%d ", a[i]);
}
}
void Print(int a[], int n){
printf("列印陣列:\n");
int i;
for(i = 0; i < n; i++){
printf("%d ", a[i]);
}
}
void Creat(int a[]){
int i,m;
printf("輸入陣列的值:");
for(i = 0; i < N; i++){
scanf("%d", &m);
a[i] = m;
}
}
int main()
{
// int a[N] = {1,-1, 0, 2, -3, 4, -1, 0, -2, 4};
int a[N];
Creat(a);
Print(a, N);
int sum = IsFuShu(a, N);
if(sum == -1)//全是負數值為0
printf("最大子段和是0");
else{
sum = maxSum1(a, N);
printf("\n蠻力法求出最大子段和是:%d\n" , sum);
sum = maxSum2(0, N-1, a);
printf("\n分治法求出最大子段和是:%d\n" , sum);
maxSum3(a, N);
}
return 0;
}
執行結果:
相關推薦
排序問題(蠻力法,分治法)
蠻力法: 選擇排序法: 演算法思想:在剩餘序列中選出最小(或最大)的關鍵字,和剩餘序列的第一個關鍵字交換位置,依次選擇下去(每次掃描結束找出最小的一個元素依次放在前面的位置),直至使整個序列有序。 程式碼實習: #include<iostream> using names
演算法設計與分析--求最大子段和問題(蠻力法、分治法、動態規劃法) C++實現
演算法設計與分析--求最大子段和問題 問題描述: 給定由n個整陣列成的序列(a1,a2, …,an),求該序列形如 的子段和的最大值,當所有整數均為負整數時,其最大子段和為0。 利用蠻力法求解: int maxSum(int a[],int n) { int ma
最大子段和問題-蠻力法、分治法、動態規劃法
蠻力法:int maxSum1(int a[], int n){ int i; int j; int maxSum = 0; for(i = 0; i < n; i++){ int sum = 0; fo
最大子段和問題:蠻力、遞迴及動態規劃
問題描述 求一個序列的最大子段和即最大連續子序列之和。例如序列[4, -3, 5, -2, -1, 2, 6, -2]的最大子段和為11=[4+(-3)+5+(-2)+(-1)+(2)+(6)]。 1. 蠻力演算法 思想:從序列首元素開始窮舉
[C++] 動態規劃之矩陣連乘、最長公共子序列、最大子段和、最長單調遞增子序列
每次 種子 () return 避免 amp 可能 text com 一、動態規劃的基本思想 動態規劃算法通常用於求解具有某種最優性質的問題。在這類問題中,可能會有許多可行解。每一個解都對應於一個值,我們希望找到具有最優值的解。 將待求解問題分解成若幹個子問題,先求
順序表應用7:最大子段和之分治遞迴法(SDUT 3664)
#include <bits/stdc++.h> using namespace std; const int maxn = 50005; int num = 0; struct node { int *elem; int len; }; void Creatlist(
【算法競賽進階指南】擴展最大子段和POJ1050ToTheMax
ace 競賽 -a set 沒有 lac 嚴格 處理 初始 最大子段和 最大子段和可以利用貪心/DP的思想來解決,我這裏沒有嚴格證明,但是思考之後覺得很有道理,如果某一段字段和,不包括該數時,前段小於0,能麽加上該數不會變的更大,能麽當前子段和應該只有當前一個數字,如果大於
順序表應用7:最大子段和之分治遞迴法 SDUT
順序表應用7:最大子段和之分治遞迴法 Time Limit: 10 ms Memory Limit: 400 KiB Problem Description 給定n(1<=n<=50000)個整數(可能為負數)組成的序列a[1],a[2],a[3]
3664-順序表應用7:最大子段和之分治遞迴法-C語言
#include <stdio.h> #include <stdlib.h> int count=0; //定義全域性變數用來記錄遞迴次數 typedef struct{ int data[50010]; int length; }Lis
順序表應用7:最大子段和之分治遞迴法
給定n(1<=n<=50000)個整數(可能為負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整數均為負數時定義子段和為0,依此定義,所求的最優值為: Max{0,a[i]+a[i+1]+…+a[j]},1&
陣列中最大最小值的蠻力法和二分法求解
方法一:蠻力法 /**用最少的比較次數找出一袋金塊中最重的和最輕的**/ /**蠻力法,相當於一次排序*/ #include<iostream> using namespace std;
最大子段和的DP算法設計與其單元測試
his 最大子數組 利用 來看 中一 tco public art 容器 表情包形象取自番劇《貓咪日常》 那我也整一個 曾幾何時,筆者是個對算法這個概念漠不關心的人,由衷地感覺它就是一種和奧數一樣華而不實的存在,即便不使用任何算法的思想我一樣能寫出能跑的程序 直到一年前
C++學習(1):最大子段和(多種解法)
多少 問題: code namespace 數據 組成 amp using () 問題:給定由n個數(可能為負數)組成的序列a1,a2,a3,...,an,求該序列子段和的最大值。 第一種解法:(最容易考慮的方法,將所有的子段一一相加,然後比較) 1 #include&
51Nod 1050 循環數組最大子段和 | DP
urn F12 int ges href 中間 art space style Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 分析: 有兩種可能,第一種為正常從[1 - n]序列中的最大子字段和;第二種為數組的total_sum -
動態規劃 ------最大子段和
動態規劃 函數 cnblogs png 規劃 font 3-9 .cn -- 1.最大子段和的問題描述 2.動態規劃的求解: 3.優化函數的遞推方程 4.動態規劃求解偽碼 5.動態規劃求解的小結: 動態規劃的
詳解 最大子段和
最大 負數 nbsp 端點 關於 一段 描述 計數器 曾經 題目名稱:最大子段和 題目描述:給出一段序列,選出其中連續且非空的一段使得這段和最大。 輸入格式: 第一行是一個正整數N,表示了序列的長度。 第2行包含N個絕對值不大於10000的整數A[i],描述了這段序列。
1049 最大子段和
return 51nod name 長度 black 最長 quest sin http 1049 最大子段和 基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 N個整數組成的序列a[1],a[2],a[3],…,a[n],求該序列如
數組的連續最大子段和
簡單 IT 設置 OS case size_t 最大 退出 gin 問題描述:輸入是一個大小為n的整型數組,要求輸出數組的任何連續子數組中的最大值。例如:輸入的數組為array[10] = {31,-41,59,26,-53,58,97,-93,-23,84};輸出最
51nod1254 最大子段和 V2
i+1 交換操作 最大子段和 body OS 另一個 體會 思路 處理 想了很久才體會出這道題的奧妙,愛恨交加的復雜情感。 思路: 題目要求必須做交換操作,那麽就有以下三種情況: 1.被交換的兩個數都在最大子段中; 2.被交換的兩個數都不在最大子段中; 3.被交換的兩個數
P1115最大子段和
cst i++ ref lld 貪心 pri pre () href 題目:https://www.luogu.org/problemnew/show/P1115 很簡明的一道題; 這裏用了遞歸分治,然而似乎還有更簡單的做法(貪心)。 代碼如下: #include<