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;
}