CF 82 D.Two out of Three

前言

全网唯一不同题解

\(f[i][j]\) 表示第 \(i\) 次选取留下来的数是 \(k\) 的最小花费

枚举前面的留下来的点 \(k\) 当前能留下的点只有 \((2*i),(2*i+1),k\) 中的一个,时间复杂度 \(O(n^2)\)

选取次数是 \(n/2\) 向上取整。因为最后什么点也不留下,\(a[n+1]=0\),所以答案可以为 \(f[m][n+1](m=n/2向上取整)\)

另外我没有写记录路径,记录一下也挺简单

Code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
    int x=0,f=1; char ch=getchar();
    while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    return x * f;
}
const int N = 1007;
int n;
int a[N];
int f[N][N];
inline int Const(int x,int y) {
    return max(a[x], a[y]);
}
int main()
{
    n = read();
    for(int i=1;i<=n;++i)
        a[i] = read();
    memset(f, 0x3f, sizeof(f));
    f[1][1] = max(a[2],a[3]); f[1][2] = max(a[1],a[3]); f[1][3] = max(a[1],a[2]);
    int m = n&1 ? n/2+1 : n/2;
    for(int i=2;i<=m;++i) {
        int x = 2*i, y = 2*i+1; // i次选取的最后两个数 
        for(int k=1;k<x;++k) {  //枚举上一次留下的数 
            f[i][x] = min(f[i][x], f[i-1][k]+Const(y,k));
            f[i][y] = min(f[i][y], f[i-1][k]+Const(x,k));
            f[i][k] = min(f[i][k], f[i-1][k]+Const(x,y));
        }
    }
    int ans = f[m][n+1];
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BaseAI/p/11757562.html
82
82!