有一題一直 TLE (無奈
於是在上周末想了一整天
終於想出個解法
題目呢...我忘了XDD
只記得是種蘋果樹,每個蘋果樹有它的價值,只能連續取,也可從中間開始取
求最大利潤為?( 如果全部賠本,就可以全不取
為最大區間和問題
INPUT:
每行第一個數 m 代表有 m 棵蘋果樹,接下來有 m 個 數字,代表蘋果樹的利潤
OUTPUT:
最大利潤
首先,來個暴力解
應該看得懂,就不加註解了(懶
#include < iostream >
using namespace std;
int main()
{
int m;
while( cin >> m )
{
int ls[m], max = 0;
for( int i = 0; i < m; i++ )
cin >> ls[i];
for( int i = 0; i < m; i++ )
for( int j = i; j < m; j++ )
{
int sum = 0;
for( int k = i; k <= j; k++ )
sum += ls[k];
if( max < sum )
max = sum;
}
cout << max << endl;
}
return 0;
}
時間複雜度為 O(n^3) 空間複雜度為 O(n)
再來是,進階版
效率較好的窮舉
把每一個數讀入時,
就加前項的總和,成為下一個總和
ex:
s[0] = ls[0]
s[1] = s[0] + ls[1]
s[2] = s[1] + ls[2]
......
再來從第一項開始扣
把每一項 s[] 的 ls[] 依序扣掉
圖解
#include < iostream >
using namespace std;
int main()
{
int m;
while( cin >> m )
{
int ls[m],s[m], input, max = 0;
// 先讀入第一項
cin >> ls[0];
s[0] = ls[0];
for( int i = 1; i < m; i++ )
{
// 依序讀入 2-m 項
cin >> input;
ls[i] = input;
// 此項和 = 前一項的和 + 輸入值
s[i] = s[i-1] + input;
if( max < s[i] )
max = s[i];
}
for( int i = 0; i < m; i++ )
for( int j = 0; j < m; j++ )
{
// 依序從 s[] 扣掉 ls[i]
s[j] -= ls[i];
if( max < s[j] )
max = s[j];
}
cout << max << endl;
}
return 0;
}
時間複雜度為 O(n^2)
空間複雜度為 O(n)
最後,其實很簡單
沒有想到罷了( 慚愧!!
假設區間和為 SUM;
只要區間和是正的,那後面就有可能有一個數,使區間和更大
如果區間和是負的,那後面就絕對不可能有一個數 X ,使得 SUM + X > X;
所以只要該段區間和為負,區間和就重置從 0 開始
#include < iostream >
using namespace std;
int main()
{
int m;
while( cin >> m )
{
int input, sum = 0, max = 0;
for( int i = 0; i < m; i++ )
{
cin >> input;
sum += input;
if( sum < 0 )
sum = input;
if( max < sum )
max = sum;
}
cout << max << endl;
}
return 0;
}
時間複雜度為 O(n)
空間複雜度為 O(1)
沒有留言:
張貼留言