题解【P3140 [USACO16FEB] Circular Barn Revisited G】
Nostopathy · · 题解
题目传送门
本题的环很难处理,考虑破环成链,这里介绍一个函数:
std::rotate(iterator start, iterator middle, iterator end);
分别表示序列第一个元素,想要开始旋转的元素及序列最后一个元素。
在本题中,每次往后旋转一位进行 dp。定义
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define pb push_back
#define rep(a, b, c, d) for(int a=b; a<=c; a+=d)
const int N = 1e2 + 5;
int n, K, r[N], dp[8][N];
void minn(int &q, int p) {
q = min(q, p);
}
signed main () {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> K;
for(int i = 0; i < n; ++ i)
cin >> r[i];
int ans = 1145141919810364364;
for(int i = 0; i < n; ++ i) { // 枚举环的开始
memset(dp, 127, sizeof dp);
dp[0][n] = 0; // 初始化
for(int k = 1; k <= K; ++ k) // 枚举开门数
for(int j = 0; j < n; ++ j) { // 枚举所在房间
int s = 0;
for(int l = j + 1; l <= n; ++ l) { // 枚举以后的房间
s += r[l - 1] * (l - j - 1); // 计算距离
minn(dp[k][j], dp[k - 1][l] + s); // 状态转移
}
}
minn(ans, dp[K][0]); // 更新答案
rotate(r, r + 1, r + n); // 后旋一位
}
cout << ans;
return 0;
}
题解来之不易,麻烦留赞再走~
最后给个友链:P1299 切孔机,题号最小能发题解题目。