寒武纪重现(HDU)- 1008(6261) - Rikka with Mutex(二分 + 错误总结)

Rikka with Mutex
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 32 Accepted Submission(s): 12

Problem Description
Sometimes, technical terms implicate some life philosophy. Mutex is one of them. On your way to dream, you may be locked by some difficulties, and you need someone to stop his step, and help you get through them.

To help you know better about the life philosophy inside mutex, Rikka comes up with a simple task. Maybe some of you know little about mutex, so she uses another scene to replace it.

There are n gates in a row, several people in the left side of the gates and all of them want to go to the right side. There are two kinds of gates: black and white. These people share energy, which is represented by a non-negative number E. Initially, E=0.

If one person walks through a white gate, he will gain one point of energy, i.e., E will be added by 1. And if one person walks through a black gate, he will lose one point of energy, i.e., E will be subtracted by 1. Since E must be a non-negative integer, if E=0, no one can walk through a black gate until someone walks through a white gate. You can assume there won’t be two people moving at the same time and all the people are selfless.

We use P to represent a black gate, V to represent a white gate and use a PV string to represent the row. Initially, all the people are at the beginning of the string, and all of them want to go through the whole string. But unfortunately, sometimes it may be impossible. So, they want to send at least one person to the right side.

Your task is to find out the minimal number of people which this group needs to achieve this goal.

For example, if the row is VPP, they need at least two people: The first person walk through the first white gate and the second person can use this point of energy to go through the whole string.

Input
The first line contains a single numner t(1≤t≤103), the number of the testcases.

For each testcase, the first line contains a PV string s(1≤|s|≤105) describing the gates.

The input guarantees that there are at most 30 testcases with |S|>1000.

Output
For each testcase, output a single integer, the answer. And if it is impossible, output −1.

Sample Input
4
VPP
VPPVVVVPPPPPPPP
VPPPPPPPPPPPPPP
P

Sample Output
2
3
14
-1

Source
寒武纪ACM金牌训练营-重现赛

Recommend
liuyiding | We have carefully selected several similar problems for you: 6263 6262 6261 6260 6259

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6261


题意给你一个字符串只包含“V” 和 “P”。“V”代表走过此时,总能量加一,P 代表走过此时,总能量减一。当要走 “P”,总能量为 0 时,就不能继续走。

:至少让一个人走完这个字符串,最少需要多少人?


解题思路:先把整个字符串相同的字符缩成 a 数组。比如 VPPVV ,缩成 :1,-2,2。然后二分一个人数 n,接着先让一个人走这个 a 序列,每走一步就看看后面 n - 1个人到当前第一个人的位置,对总能量有没有贡献。若有,则把后面 n - 1个人移到当前第一个人的位置且总能量加上贡献,否则,就接着往下走,直到走不了为止。

那怎么保证后面 n - 1 个人一定能走到当前第一个人的位置呢?
比如:当 n 个人都在 i 位置时的总能量为 E1,接着当第一个人从 i 走到了 j 且走到 j 时的总能量 E2 是大于等于之前的总能量 E1说明后面每 n - 1 个人也是能走到 j 位置的。


错误总结:不应该是走到不能走的时候把后面的 n - 1 个人移到当前不能走的位置看看有没有贡献。而是每走一步,都要看看把后面的 n - 1 个人移到当前位置看看有没有贡献,有就移,没有就不移。也就是要把每一步的状态给列出来。


代码如下

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#include<map>
#include<cstring>
using namespace std;

const int maxn = 1e5 + 5;
char s[maxn];
long long a[maxn];
int len,all;

void Init(){
    bool flag;
    if(s[1] == 'V') flag = 1;
    else flag = 0;
    long long sum = 0LL;all = 0;
    for(int i = 1;i <= len;i++){
        if(s[i] == 'V' && flag) sum++;
        else if(s[i] == 'V' && !flag) a[++all] = -sum,sum = 1LL,flag = 1;
        else if(s[i] == 'P' && !flag) sum++;
        else if(s[i] == 'P' && flag) a[++all] = sum,sum = 1LL,flag = 0;
    }
    if(flag) a[++all] = sum;
    else a[++all] = -sum;
}

bool check(long long mid){
    long long E,sum;
    E = 1LL * a[1] * mid;
    sum = E;
    for(int i = 2;i <= all + 1;i++){
        if(E < 0) return false;
        if(i == all + 1) return true;
        E += a[i];
        if(E >= sum){
            E += (mid - 1LL) * (E - sum) * 1LL;
            sum = E;
        }
    }
}

int main(){
    int t;
    cin >> t;
    while(t--){
        cin >> s + 1;
        len = strlen(s + 1);
        Init();
        int l = 1,r = len,mid;
        while(l <= r){
            mid = (l + r) >> 1;
            if(check(mid)) r = mid - 1;
            else l = mid + 1;
        }
        if(l >= len) printf("-1\n");
        else printf("%d\n",l);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值