两个沙漏分别可以计时N和M,初始状态两个沙漏所有的沙子都在上方
在任意一个沙漏到时间时(即一个确定的时间点),可以翻转沙漏,可以翻一个或者两个,也可以不翻转
求能否用这两个沙漏计时K,可以输出1,否则输出0
限制:
1<=N,M,K<=1000
总翻转次数不大于10,如果两个沙漏同时翻转算一次
输入:
用例数T
N, M, K
思路:
这个题并不要求最少翻转几次,而是只需要知道有没有可行解
所以其实是一道DFS题目
input:
9
3 5 7
12 13 118
8 3 9
1 103 18
4 3 41
5 7 17
5 16 23
5 19 26
7 27 36
output:
#1 1
#2 0
#3 1
#4 1
#5 0
#6 1
#7 1
#8 1
#9 1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int T, N, M, K, answer;
void dfs(int time, int a, int b, int steps){
// 如果已经不可能或者已经找到可行解,则在这里剪枝
if (time > K || steps >= 10 || answer == 1){
return;
}
// 当前的time再加上当前的状态可以计时的a或者b,如果能正好达到K,则说明可行,直接answer赋1返回。注意这里这样写,决定上面的剪枝必须是 steps >= 10,不能只是>
if (time + a == K || time + b == K){
answer = 1;
return;
}
//根据a和b的大小分两种情况考虑
if (a <= b){
// 当较小的沙漏a流完时的三种情况
// 这里对较小的沙漏a为0的情况进行剪枝
/* 注意这里这个剪枝,不能跟上面的if并在一起,因为在较小的a=0时,也需要考虑较大的沙漏b流完时的三种情况
参考如下几个case:
5 16 23
5 19 26
7 27 36
*/
if (a != 0){
dfs(time + a, N, b - a, steps + 1);
dfs(time + a, 0, M - b + a, steps + 1); // M - b 是在这步之前,第二个沙漏下面初始的沙子
dfs(time + a, N, M - b + a, steps + 1);
}
// 当较大的沙漏b流完时的三种情况(翻的是满的,不翻的是0)
// 不需要考虑两个沙漏都为0的情况,因为这种情况直接就over了
dfs(time + b, N, 0, steps + 1);
dfs(time + b, 0, M, steps + 1);
dfs(time + b, N, M, steps + 1);
}
else{
// 当较小的沙漏b流完时的三种情况
if (b != 0){
dfs(time + b, a - b, M, steps + 1);
dfs(time + b, N - a + b, 0, steps + 1); // N - a 是在这步之前,第一个沙漏下面初始的沙子
dfs(time + b, N - a + b, M, steps + 1);
}
// 当较大的沙漏a流完时的三种情况(翻的是满的,不翻的是0)
dfs(time + a, N, 0, steps + 1);
dfs(time + a, 0, M, steps + 1);
dfs(time + a, N, M, steps + 1);
}
}
int main(int argc, char** argv) {
freopen("sample_input.txt", "r", stdin);
setbuf(stdout, NULL);
scanf("%d", &T);
for (int test_case = 1; test_case <= T; ++test_case){
scanf("%d %d %d", &N, &M, &K);
answer = 0;
// 初始状态
dfs(0, N, M, 0);
printf("#%d %d\n", test_case, answer);
}
return 0;
}