这个题目比赛的时候想了好久,也没有做出来,当时想是个dp或者贪心,想着贪心的题目,dp应该也能做,所以就一直在dp上想,但是没有解决办法。今天有空就看了看这个题目。codeforces给的标签是贪心,自己就往贪心上想了想,最后解决了。其实用贪心的话并不难想,先判断是否可以度过整个冬天,这个比较简单就不再多说了。假设每次遇到0下的天气都需要换成冬天用的轮胎,而用完这一天之后就换成夏天用的轮胎,这样的话最大的交换次数就是2*c(c表示温度为0下的天数)。然后,记录相邻两个气温小于0度的天气之间相隔的天数和冬用的轮胎数大于温度为0下的天气的数量tmp。然后根据相隔天数从小往大贪心,当相隔的天数小于tmp时,交换的次数减2。最后注意判断如果 n - 最后一次出现0下的日期小于tmp的话,最终结果减1。说到dp,后来看了网上也有人用dp来做,将这个问题转化成了0-1背包的问题。这种想法真的值的学习。下面放上我写的贪心的代码。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 200010;
struct Node{
int u, x, y;
bool operator < (const Node& args) const{
return u < args.u;
}
}p[MAX];
int a[MAX];
int main(int argc, char const *argv[])
{
/* code */
int n, k;
while (scanf("%d%d", &n,&k) != EOF){
int c = 0, l = 0, r = 0, cnt = 0;
for (int i = 1; i<=n; i++){
scanf("%d", &a[i]);
if (a[i] < 0){
c++;
if (l == 0){
l = i;
}else{
r = i;
p[cnt++] = (Node){r-l-1, l, r};
l = r;
}
}
}
if (c > k){
printf("-1\n");
continue;
}else if (c == 0){
printf("0\n");
continue;
}
int last = r == 0 ? n-l : n - r;
sort(p, p+cnt);
/*
for (int i = 0; i<cnt; i++){
printf("%d %d %d\n", p[i].u, p[i].x, p[i].y);
}
*/
int tmp = k - c;
int res = c * 2;
for (int i = 0; i<cnt; i++){
if (p[i].u <= tmp){
tmp -= p[i].u;
res -= 2;
}
}
if (tmp >= last){
res -= 1;
}
printf("%d\n", res);
}
return 0;
}