彗星OJ - コンテスト#8 Cタイトルルーンパワー動的プログラミングDP

トピックリンク: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が記録されます。

公開された19元の記事 ウォンの賞賛0 ビュー501

おすすめ

転載: blog.csdn.net/qq_43317133/article/details/99674414
おすすめ