ダイナミックプログラミング
そして、最大の連続サブシーケンス
解決のための基本的な方法
方法
のDP [i]を表すA [1]、最大連続サブシーケンスA [i]が
最終的な最大値と隣接サブ= DP [NUM]
#include<iostream>
using namespace std;
const int N = 10000;
int A[N];
int dp[N];
int main()
{
int num = 6;
for (int i = 1; i <= num; i++)
cin >> A[i];
int temp = -999999;
int sum = 0;
for (int i = num; i >= 1; i--)
{
sum += A[i];
if (sum > temp)
temp = sum;
dp[i] = temp;
if (sum < 0)
sum = 0;
}
printf("%d", dp[1]);
system("pause");
return 0;
}
方法二
DP [I]最大値を表し、A [i]が連続した配列の終わりには、
配列全体を通して、DP配列全体を決定した後、最大値が最大連続サブシーケンスで見つけると
3可動正規点:
状態変数:DP [i]の
境界:DP [1] = A [ 1]
の状態遷移方程式:DP [I] = MAX( A [i]が、DP [I-1] + A [I ])
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10000;
int A[N];
int dp[N];
int main()
{
int num = 6;
for (int i = 1; i <= num; i++)
cin >> A[i];
//边界
dp[1] = A[1];
for (int i = 2; i <=num; i++)
{
dp[i] = max(dp[i - 1] + A[i], A[i]);
}
int k = dp[1];
for (int i = 2; i <=num ; i++)
{
if (dp[i] > k)
k = dp[i];
}
printf("%d",k);
system("pause");
return 0;
}
例1最大合計
出典:2479年最大SUM
#include<iostream>
using namespace std;
const int N = 100010;
int A[N];
int dpr[N]; //从右向左dp,求出连续子序列的最大和。dp[i]表示从A[1]到A[i]中连续子序列的最大和
int dpl[N]; //从左向右dp,求出连续子序列的最大和。dp[i]表示从A[i]到A[N]中连续子序列的最大和
int main()
{
int T,k;
scanf("%d", &T);
while (T--)
{
scanf("%d", &k);
//将整个序列读入
for (int i = 1; i <= k; i++)
cin >> A[i];
//求解dpr[i]
int sum = 0;
int temp = -9999999;
for (int i = 1; i <= k; i++)
{
sum += A[i];
if (sum > temp)
temp = sum;
dpr[i] = temp;
if (sum < 0)
sum = 0;
}
sum = 0; temp = -9999999;
//求解dpl[i]
for (int i = k; i >=1; i--)
{
sum += A[i];
if (sum > temp)
temp = sum;
dpl[i] = temp;
if (sum < 0)
sum = 0;
}
int MaxSum = -9999999;
for (int i = 1; i < k; i++)
{
int t = dpr[i] + dpl[i + 1];
if (MaxSum < t)
MaxSum = t;
}
cout << MaxSum << endl;
}
system("pause");
return 0;
}
ベストプラス表現
例
POJ 4103は、正方形を強化しました
アイデア:方法は(i、jは、n個):ノードからの方法は、(i、j)はステップ数nを歩き始めました
方法(I、J、N)=通り(I、J-1、N-1)+方法(I、J + 1、N-1)+方法(I + 1、J、N-1)
使用アレイVIS [I] [J]標識されたノード(i、j)を介してか
チップ:
- 0か否かが最初に判定されたNは、ノード(i、j)には標識されます
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int vis[50][50];
int ways(int i, int j, int n)
{
if (n == 0)
{
return 1;
}
int num = 0;
if (!vis[i][j - 1])
{
vis[i][j - 1] = 1;
num += ways(i, j - 1, n - 1);
vis[i][j - 1] = 0;
}
if (!vis[i][j + 1])
{
vis[i][j + 1] = 1;
num += ways(i, j + 1, n - 1);
vis[i][j + 1] = 0;
}
if (!vis[i+1][j])
{
vis[i + 1][j] = 1;
num += ways(i+1, j, n - 1);
vis[i + 1][j] = 0;
}
return num;
}
int main()
{
int n;
cin >> n;
memset(vis, 0, sizeof(vis));
vis[0][25] = 1;
cout << ways(0, 25, n) << endl;
return 0;
}