1. 程式人生 > >U45490 還沒想好名字的題Ⅱ

U45490 還沒想好名字的題Ⅱ

這一題的環狀板

Solution

暴力斷環為鏈, 列舉起點跑 \(n\)\(DP\), 取最小值即可

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cmath>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 419;
int num, m;
double dp[maxn][maxn], a[maxn], sum[maxn], ave;
double DP(int l, int r){
    REP(i, 0, num)REP(j, 0, m)dp[i][j] = 1e19;
    dp[0][0] = 0;
    REP(i, l, r)
    REP(j, 1, i)
    REP(k, l - 1, i - 1)
    dp[i][j] = min(dp[i][j], 
    dp[k][j - 1] + ((sum[i] - sum[k] - ave) * (sum[i] - sum[k] - ave)));
    return dp[r][m];
    }
int main(){
    num = RD(), m = RD();
    REP(i, 1, num)a[i] = a[i + num] = RD();//斷環為鏈
    REP(i, 1, num * 2)sum[i] = sum[i - 1] + a[i];
    ave = sum[num] / (m * 1.0);
    double ans = 1e9;
    REP(i, 1, num)ans = min(ans, DP(i, i + num));
    printf("%.2lf\n", sqrt(ans / (double)m));
    return 0;
    }