AcWing 1843. 圆形牛棚
题目链接
1843. 圆形牛棚
作为当代建筑的爱好者,农夫约翰建造了一个完美圆环形状的新牛棚。
牛棚内部有 \(n\) 个房间,围成一个环形,按顺时针编号为 \(1~n\)。
每个房间都既有通向相邻两个房间的门,也有通向牛棚外部的门。
约翰想让第 \(i\) 个房间内恰好有 \(r_i\) 头牛。
为了让奶牛们有序的进入牛棚,他计划打开一个外门,让牛从该门进入。
然后,每头牛顺时针穿过房间,直到到达合适的房间为止。
约翰希望通过合理选择打开的门,使得所有奶牛的行走距离之和尽可能小(这里只考虑每头牛进入牛棚以后的行走距离)。
请确定他的奶牛需要行走的最小总距离。
输入格式
第一行包含整数 $n4。
接下来 \(n\) 行,包含 \(r_1,…,r_n\)。
输出格式
输出所有奶牛需要行走的最小总距离。
数据范围
\(3≤n≤1000\),
\(1≤r_i≤100\)
输入样例:
5
4
7
8
6
4
输出样例:
48
样例解释
最佳方案是让奶牛们从第二个房间进入。
解题思路
暴力
题意即求解 \(0\times a[i]+1 \times a[i+1] + \dots + (n-1)\times a[j]\),不妨暴力枚举起始点
- 时间复杂度:\(O(n^2)\)
代码
// Problem: 圆形牛棚
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1845/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// %%%Skyqwq
#include
#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair PII;
template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int n,a[2005];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i+n]=a[i];
}
int res=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
int t=0,dis=0,j=i;
while(t
前缀和
考虑从任意一处开始,结果为:\(0\times a[i]+1 \times a[i+1] + \dots + (n-1)\times a[j]\),下一个转移状态为:\((n-1)\times a[i]+0 \times a[i+1] + \dots + (n-2)\times a[j]\),两个状态之间相差:\(a[i+1]+\dots+a[j]-(n-1)\times a[i]\),其中 \(a[i+1]+\dots+a[j]\) 为长度为 \(n-1\) 的前缀和,对此,我们只需要遍历起始位置,每次转移状态时更新对应的值即可
- 时间复杂度:\(O(n)\)
代码
// Problem: 圆形牛棚
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1845/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// %%%Skyqwq
#include
#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair PII;
template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int sum,n,a[1005],b[2005];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=b[i+n]=a[i];
sum+=(i-1)*a[i];
}
for(int i=1;i<=2*n;i++)b[i]+=b[i-1];
int res=sum;
for(int i=2;i<=n;i++)
{
sum=sum-(b[i+n-2]-b[i-1])+(n-1)*a[i-1];
res=min(res,sum);
}
printf("%d",res);
return 0;
}