题目
你在动物收容所工作,负责喂养动物。
你一共准备了 D 份狗粮和 C 份猫粮。
一共有 N 只动物排队等候用餐,有的是狗,有的是猫。
当然,也有可能全都是狗或者全都是猫。
我们可以用一个长度为 N 的由大写字母 C 和 D 组成的字符串 S 来表示队列中猫狗的顺序。
如果队列中第 i 只动物是猫,则第 i 个字符为 C。
如果队列中第 i 只动物是狗,则第 i 个字符为 D。
动物们严格按照排队顺序依次进食。
每只狗吃一份狗粮,每只猫吃一份猫粮。
此外,你还有额外的猫粮。
每当一条狗吃完一份狗粮,你就会为猫多提供 M 份猫粮。
每只动物都只会在排在其前面的所有动物都进食完毕后,才肯进食。
这也就意味着,当轮到某只动物进食,但是却没有相应的食物时,它和排在它后面的所有动物都会因此无法进食。
请问,在这种情况下,队列中的所有狗能否都得到喂食。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含四个整数 N,D,C,M。
第二行包含一个长度为 N 的由大写字母 C 和 D 组成的字符串 S。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: y
,其中 x 为组别编号(从 1 开始),如果所有狗都能得到喂食,则 y 为 YES
,否则 y 为 NO
。
数据范围
1 ≤ T ≤ 100,
1 ≤ N ≤ 104,
0 ≤ D,C ≤ 106,
0 ≤ M ≤ 106。
输入样例1:
3
6 10 4 0
CCDCDD
4 1 2 0
CCCC
4 2 1 0
DCCD
输出样例1:
Case #1: YES
Case #2: YES
Case #3: NO
样例1解释
在 Case 1 中,一共有 10 份狗粮和 4 份猫粮。
- 前两只动物是猫,喂食它们后,还剩下 2 份猫粮。
- 接下来是一只狗,喂食它后,还剩下 9 份狗粮。
- 然后是一只猫,喂食它后,还剩下 1 份猫粮。
- 最后是两只狗,喂食它们后,还剩下 7 份狗粮。
所有狗都被喂食。
在 Case 2 中,没有狗,因此,所有狗(0 只)都被喂食了。
在 Case 3 中,第二只狗前面的猫得不到喂食,所有第二只狗也没法得到喂食。
`输入样例2:
2
12 4 2 2
CDCCCDCCDCDC
8 2 1 3
DCCCCCDC
输出样例2:
Case #1: YES
Case #2: NO
样例2解释
在 Case 1 中,每只狗喂食完毕后,都会额外得到两份猫粮。
- 首先是一只猫,喂食它后,还剩下 1 份猫粮。
- 接下来是一只狗,喂食它后,还剩下 3 份狗粮和 3 份猫粮。
- 接下来是三只猫,喂食它们后,还剩下 3 份狗粮和 0 份猫粮。
- 接下来是一只狗,喂食它后,还剩下 2 份狗粮和 2 份猫粮。
- 接下来是两只猫,喂食它们后,还剩下 2 份狗粮和 0 份猫粮。
- 接下来是一只狗,喂食它后,还剩下 1 份狗粮和 2 份猫粮。
- 接下来是一只猫,喂食它后,还剩下 1 份狗粮和 1 份猫粮。
- 接下来是最后一只狗,喂食它后,还剩下 0 份狗粮和 3 份猫粮。
所有狗都被喂食。
在 Case 2 中,第二只狗前面的猫得不到喂食,所有第二只狗也没法得到喂食。
解题思路
该题最多有 100 组数据,每组数据最多有 104 只动物,所以暴力解题也仅需遍历 106 次,时间复杂度允许,所以可以直接选择模拟。
注意:
- 每成功喂一条狗,猫粮会增加 m;
- 由于猫粮的总数会增加,所以猫粮的总数会超出 int 的范围,需要使用 long;
- 只需要判断狗能否喂完即可,不用关心猫的状态;
- 如果喂到当前狗没有了狗粮,说明狗不能喂完;
- 如果当前猫没有了猫粮,则需要遍历剩下所有动物,如果该猫后面不再有狗,说明所有狗已经喂完;如果还有狗,则会因为该猫被阻塞而无法成功投喂该猫后的所有狗。
AC代码
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(System.out);
int t = in.nextInt();
int n = 0;
long d = 0;
long c = 0;
long m = 0;
boolean flag = false;
char[] ch;
for(int i = 1; i <= t; i++) {
n = in.nextInt();
d = in.nextLong();
c = in.nextLong();
m = in.nextLong();
ch = in.next().toCharArray();
flag = false;
for(int j = 0; j < n; j++) {
if(ch[j] == 'D') {
d--;
c += m; // 每喂一条狗,猫粮增加 m
}
else {
c--;
}
if(d < 0) { // 当 d < 0,说明刚才那条狗投喂失败
flag = true;
break;
}
else if(c < 0) { // 当猫粮没了,喂动物受阻,判断猫后面是否还有狗
for(; j < n; j++) {
if(ch[j] == 'D') { // 如果猫后面还有狗说明狗不能全部喂完
flag = true;
break;
}
}
}
}
if(flag) out.println("Case #" + i + ": NO");
else out.println("Case #" + i + ": YES");
}
out.flush();
}
public static class InputReader {
BufferedReader reader;
StringTokenizer tokenizer;
public InputReader(InputStream in) {
reader = new BufferedReader(new InputStreamReader(in));
}
public String next() throws IOException {
while(tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public Long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}
c++
#include<bits/stdc++.h>
using namespace std;
int main()
{
long t, n, d, c, m;
string s;
bool flag;
cin >> t;
for(int i = 1; i <= t; i++)
{
cin >> n >> d >> c >> m;
cin >> s;
flag = false;
for(int j = 0; j < n; j++)
{
if(s[j] == 'D')
{
d--;
c += m; // 每喂一条狗,猫粮增加 m
}
else
{
c--;
}
if(d < 0) // 当 d < 0,说明刚才那条狗投喂失败
{
flag = true;
break;
}
else if(c < 0) // 当猫粮没了,喂动物受阻,判断猫后面是否还有狗
{
for(; j < n; j++)
{
if(s[j] == 'D') // 如果猫后面还有狗说明狗不能全部喂完
{
flag = true;
break;
}
}
}
}
if(flag) cout << "Case #" << i << ": NO" << endl;
else cout << "Case #" << i << ": YES" << endl;
}
return 0;
}