→题目链接←
这个题就是暴力找到山,然后每次删掉花费最小的山就好
注意当你删掉一个山后有可能会使其他的山发生变化,每次重新扫一遍就好
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct hill{
int l,r;
int h;
int sum;
};
hill v[1010];
int n,k;
int a[1010];
bool vis[1010];
int num=0;
void check_hill(int p){
int x=v[p].l,y=v[p].r;
bool ll=false,rr=false;
while(x>=1 && a[x-1]<=a[x]){
x--;
if(a[x]<a[v[p].l])ll=true;
}
while(y<=n && a[y+1]<=a[y]){
y++;
if(a[y]<a[v[p].r])rr=true;
}
v[p].l=x;
v[p].r=y;
v[p].h=max(a[x],a[y]);
v[p].sum=0;
for(int j=x; j<=y; j++)if(a[j]>v[p].h)v[p].sum+=a[j]-v[p].h;
}
int main(){
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
}
for(int i=1; i<=n; i++){
if(vis[i])continue;
vis[i]=true;
int x=i,y=i;
bool ll=false,rr=false;
while(x>=1 && a[x-1]<=a[x]){
x--;
vis[x]=true;
if(a[x]<a[i])ll=true;
}
while(y<=n && a[y+1]<=a[y]){
y++;
vis[y]=true;
if(a[y]<a[i])rr=true;
}
if(ll && rr){
v[num].l=x;
v[num].r=y;
v[num].h=max(a[x],a[y]);
v[num].sum=0;
for(int j=x; j<=y; j++)if(a[j]>v[num].h)v[num].sum+=a[j]-v[num].h;
num++;
}
}
int ans=0;
int hillnum=num;
memset(vis,0,sizeof(vis));
while(hillnum>k){
int Min=1000000010,p;
for(int i=0; i<num; i++){
if(vis[i])continue;
if(v[i].sum<Min)Min=v[i].sum,p=i;
}
ans+=Min;
vis[p]=true;
hillnum--;
for(int i=v[p].l; i<=v[p].r; i++){
a[i]=min(a[i],v[p].h);
}
for(int i=0; i<num; i++){
if(!vis[i])check_hill(i);
}
}
printf("%d\n",ans);
return 0;
}