题目描述
Abstinence(戒酒)岛的居民们酷爱一种无酒精啤酒。以前这种啤酒都是从波兰进口,但今年居民们想建一个自己的啤酒厂。岛上所有的城市都坐落在海边,并且由一条沿海岸线的环岛高速路连接。酒厂的投资者收集了关于啤酒需求量的信息,即每天各城市消费的啤酒桶数。另外还知道相邻城市之间的距离。每桶啤酒每英里的运费是1元。日运费是将所需要的啤酒从酒厂运到所有城市所必需的运费之和。日运费的多少和酒厂的选址有关。投资者想找到一个合适的城市来修建酒厂,以使得日运费最小。
请设计一个程序,输入城市的数目、相邻两城市间的距离以及每个城市消费的啤酒桶数,输出最小的日运费。
输入描述
第一行是一个整数n(5 <= n <= 10000) ,表示城市的数目。 城市沿高速路编号,使得相邻的城市的编号也相邻(城市1和n也被认为是相邻)。 以下的n行,每行有两个非负整数。第I+1行的数 zi、di分别是城市I每日的啤酒消费量(桶)和从城市I沿高速路到下一个城市的距离(英里)。高速路的总长不会超过65535 英里。每座城市的日消费量不会超过255桶。
输出描述
一个整数,表示所需的最小日运费(元)。
样例输入
6
1 2
2 3
1 2
5 2
1 10
2 3
样例输出
41
分析
参考了一位大神的做法,直接暴力。
#include<iostream>
using namespace std;
#define N 20000 + 10
#define INF 0x3f3f3f3f3f3f//足够大的数
#define ll long long
int n;
ll a[N],b[N],c[N];
ll sum;
ll ans = INF;
int main()
{
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i] >> b[i];
for(int i = 0; i < n; i++) {
//处理环型
a[i + n] = a[i];
b[i + n] = b[i];
sum += b[i];//记录一下总长
}
/*外层循环为酒厂地址,内层循环得到日运费
因为复制了一份,变为了线性,所以只需要往后推,同时控制长度*/
for(int i = 0; i < n; i++) {
ll t = 0;
for(int j = i + n - 1; j >= i + 1; j--) {//这里需要从后往前推,不理解可以模拟一下过程
t += b[j];
c[i] += min(t,sum - t) * a[j];//这里是将环分为两半,找到较短的一半
}
}
for(int i = 0; i < n; i++)
ans = min(ans,c[i]);
cout << ans << endl;
return 0;
}