G
题意:
当前在
(
0
,
0
)
(0,0)
(0,0)位置,最终需要到达
(
n
,
n
)
(n,n)
(n,n)位置。
你一个可以进行
n
n
n次方向的选择,但是必须是交叉式,即一次
x
x
x方向,一次
y
y
y方向或者一次
y
y
y方向,一次
x
x
x方向。每个方向可以走至多
n
n
n次直到你已经到达
(
n
,
n
)
(n,n)
(n,n),但是不允许大于
n
n
n或小于
0
0
0。每个方向的单位路程花费为
c
i
c_i
ci ,问所有方向和路程的选择中,花费最少是多少。
数据范围:
2
≤
n
≤
1
0
5
,
1
≤
c
i
≤
1
0
9
2\leq n\leq 10^5,1\leq c_i\leq 10^9
2≤n≤105,1≤ci≤109
题解:
由于两个方向是独立的,所以你可以单独考虑这两个方向,但是注意整体的方向选择是交叉的。贪心的想法是,单位花费最少的
c
i
c_i
ci将走最多的路,因此我们给
c
i
c_i
ci走上当前需要走的最多的路,其余的必须到达
c
i
c_i
ci的单位花费只给
1
1
1单位长度。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int c[N], n;
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
ll res = 1ll * (c[1] + c[2]) * n;
int c1 = 1, c2 = 1;
ll mn1 = c[1], mn2 = c[2], sum = c[1] + c[2];
for(int i = 3; i <= n; ++i) {
if(i & 1) mn1 = min(mn1, (ll)c[i]), ++c1;
else mn2 = min(mn2, (ll)c[i]), ++c2;
sum += c[i];
res = min(res, sum + mn1 * (n - c1) + mn2 * (n - c2));
}
printf("%lld\n", res);
}
int main()
{
int T = 1;
scanf("%d", &T);
for(int i = 1; i <= T; ++i) solve();
return 0;
}