链接:https://ac.nowcoder.com/acm/contest/332/H
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小B来到了一个异世界,成为了肥猪之王。
在这个异世界,共有n种肥猪,编号分别为1,...,n。
小B希望集齐这n种肥猪。
召集肥猪有两种方式:
1. 花费a[i]的金币召唤一只编号为i的肥猪。
2. 花费x的金币使所有已召集的肥猪进化。
即编号为i的肥猪编号变成i+1,特殊的,编号为n的肥猪编号变成1。
请问小B最少要花多少金币才能集齐n种肥猪。
输入描述:
第一行两个正整数n,x 接下来n行,第i行一个正整数a[i]
输出描述:
一个数表示答案
示例1
输入
2 10 1 20
输出
12
示例2
输入
4 10 1 2 3 4
输出
10
备注:
1≤n≤2000,1≤x,a[i]≤109
题意:题意一开始把我弄蒙了,后来看了题解才发现题目里的第二条是,全部的猪都进化,注意这一点就没问题了。
题解:两种写法,一种是用数组写,一种是用优先队列写,总之,都是求区间最小值,为什么求区间最小值呢?因为第二条是全部进化,这样的话,比如说进行两次进化,那么3号就由1号来的,这样的话就需要找到1——3区间的最小值,因为这个区间里的经过<=2次就可以,题目说的不清楚,应该是满足小于等于进化次数。。
注意:如果题目卡常数的话,就要数组写了,不过卡常数的题目不多~~~,这个题不卡常数~~上代码,两种方法
数组:
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int MAX = 2222;
ll a[MAX],b[MAX];
int main(){
ll ans=0;
ll n,x;
cin >> n >> x;
for (int i = 0; i < n;i++){
cin >> a[i];
ans+=a[i];//ans是没进化的时候,得到全部的类型花的总金币
b[i]=a[i];
}
ll tmp=ans;
for (int i = 0; i < n;i++){
for (int j = 0; j < n;j++){
if(b[(i+j+1)%n]>a[j]){//找区间最小值的方法
tmp=tmp-b[(i+j+1)%n]+a[j];//两种表示一样的,移项就可以啦,这一种好理解
//tmp-=(b[(i+j+1)%n]-a[j]);
b[(i+j+1)%n]=a[j];
}
}
ans=min(ans,tmp+(i+1)*x);//(i+1)代表进化次数
}
cout << ans << endl;
return 0;
}
优先队列:
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int MAX = 2222;
priority_queue<ll,vector<ll>,greater<ll> > p[MAX];
ll a[MAX];
int main(){
ll ans=0;
ll n,x;
cin >> n >> x;
for (int i = 0; i < n;i++){
cin >> a[i];
ans+=a[i];//没采取进化的时候,得到所有类型所需的总金币
p[i].push(a[i]);
}
ll tmp;
for (int i = 0; i < n;i++){
tmp=0;
for (int j = 0; j < n;j++){
p[j].push(a[(j-i+n)%n]);//求区间最小值的方法
tmp+=p[j].top();
}
ans=min(ans,i*x+tmp);//i代表进化次数,i从0,是因为优先队列是从区间长度为1,开始的,也就是没采取进化措施~~
}
cout << ans << endl;
return 0;
}