トピックリンク:httpsの:? //Cometoj.com/contest/58/problem/C PROBLEM_ID = 2760
コードこの質問は非常に簡単です、主なポイントは、ピットがあります。私たちは、このような二第一の融合のどちらとして、ダイナミックに取得する方法を計画を開始する予定を考えると、最初の二つの融合され、その後、* k個の間隔を扱うことがあり、または順序が逆転しました。そう考えて、動的計画の全体のプロセスは非常に複雑になります。
私たちは、視野の一部を行く、または私たちが見つけるものをシミュレートするために時間がかかり、すべてのケースではありません* k個のルーン文字に関係なく、選択の、そして最終的にはルーンにマージする許可すればしかし、その後、総エネルギーが放出します実際には、それは変更されません。私たちがしなければならない、実際には、可能な限り小さく、最終的なエネルギーを作るために、* k個の間隔、どこに終了し、開始する場所から間隔を持っているかどうかを決定することです。
順序は、統合に影響を与えませんので、DPの寸法は、セットに実際にある。この場合、各最初の配列に直接隣接し、私たちは、直接コードを理解し、それぞれ4つの状態があり、過去に再び、O(n)を統合していますコメントで彼は続けました。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <string.h>
const int MAX=1e6+5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
/// https://cometoj.com/contest/58/problem/C?problem_id=2760
ll a[MAX], b[MAX], dp[MAX][5];
int main()
{
int i, j, n, k;
cin >> n >> k;
for (i=0; i<n; i++)
scanf("%lld%lld", &a[i], &b[i]);
for (i=1; i<n; i++)/// 状态数组dp从上向下滚动,对应符石从左到右
{
dp[i][0] = dp[i-1][0] + a[i]*b[i-1];/// 直接与左边符石融合的情况,顺带上左边
///符石和左边的左边符石直接融合产生的能量。dp[i][0]的记录只是为了dp[i][1]的
///选择做铺垫,真正的完全不*k的情况会在dp[i][2]被选择
dp[i][1] = min(dp[i-1][0]+k*a[i]*b[i-1], dp[i-1][1]+k*k*a[i]*b[i-1]);/// 两种
///状态进行选择,一种是左符石没*k,i符石自己乘;一种是i-1符石和i符石一起乘,
///取最优情况记录下来,反正不论选哪个,dp[i][1]记录的都是*k区间覆盖到i符石
///的情况
dp[i][2] = min(dp[i-1][1]+k*a[i]*b[i-1], dp[i-1][2]+a[i]*b[i-1]);/// 也是二选
///一,一种是i-1符石*k了,到i这里断了不乘了;一种是i-1没乘,i也不乘。所以
///dp[i][2]记录的是*k区间没覆盖到i符石的情况
}
cout << min(dp[n-1][1], dp[n-1][2]);/// 这里最终取最优
return 0;
}
実際には、最終的にいくつかの間隔が存在する領域との間にない、Kこれらの二つの結果をK、最適なソリューションは、最終結果出そうMAX、各状態のエネルギーの放出をDPが記録されます。