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 <bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }

template <typename T> 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<n)
		{
			dis+=a[j]*t;
			t++,j++;
		}
		res=min(res,dis);
	}
	printf("%d",res);
	return 0;
}

前缀和

考虑从任意一处开始,结果为:\(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 <bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }

template <typename T> 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;
}
posted @ 2022-01-25 23:07  zyy2001  阅读(66)  评论(0编辑  收藏  举报