uva10400 - Game Show Math(回溯+剪枝)

本文深入探讨了解决UVA 10400 GameShowMath问题的回溯与剪枝算法,详细解释了如何使用这些算法来解决给定数字与目标数之间的数学运算问题,特别关注了操作顺序限制、除法应用条件及结果范围限制。通过实例代码展示了解题过程,帮助读者理解并掌握回溯算法在解决此类问题时的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:uva10400 - Game Show Math(回溯+剪枝)


题目大意:给出N个数,并且给出一个目标数值,要求用上面的数字(全部),并且顺序不能乱,然后用+-*/这些操作,问最终能不能得到目标数值。这里要注意给出的数会在【-32000,32000】之间, 并且要用除法的时候,只有在能整除的时候才能用。并且中间计算结果不能超过【-32000,32000】范围。如果超过这个操作不能做。

解题思路:回溯加剪枝,将每一层计算的结果都保存下来,如果在同一层发现值出现过,并且之前计算发现这样往后是得不到目标值的,那么就可以直接剪掉。

                  这题题意没有读清楚,结果WA了好多遍。

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const int N = 105;
const int M = 70000;
const int maxn = 32000;

char op[N];
int num[N];
int n;
int target;
int flag;
char OP[4] = {'*', '-', '+', '/'};
int vis[N][M];

void dfs (int k, int sum) {
	
	if (k == n - 1) {
		
/*	for (int i = 0; i < n - 1; i++)
			printf ("%c ", op[i]);
		printf ("\n");
		printf ("%d\n", sum);*/
		if (sum == target)
			flag = 1;
		return;
	}

	int temp;
	for (int i = 0; i < 4; i++) {
		
		op[k] = OP[i];	
		switch (OP[i]) {

			case '+' : temp = sum + num[k + 1];
					   if (abs (temp) > maxn)
						   break;
					   if (vis[k][temp + maxn])
						   break;
					   dfs (k + 1, temp); break;
			case '-' : temp = sum - num[k + 1];
					   if (abs (temp) > maxn)
						   break;
					   if (vis[k][temp + maxn])
						   break;
					   dfs (k + 1, temp); break;
			case '/' : if (sum % num[k + 1] == 0) {

						   temp = sum / num[k + 1];
						   if (abs (temp) > maxn)
							   break;
					   	if (vis[k][temp + maxn])
						   break;
					   	dfs (k + 1, temp); 
					   }
					   break;
			case '*' : temp = sum * num[k + 1];
					   if (abs (temp) > maxn)
						   break;
					   if (vis[k][temp + maxn])
						   break;
					   dfs (k + 1, temp); break;
		}
		if (flag)
			return;
		else if (abs (temp) <= maxn && !vis[k][temp + maxn])
			 vis[k][temp + maxn] = 1;
	}
}

int main () {

	int t;
	scanf ("%d", &t);
	while (t--) {
	
		scanf ("%d", &n);
		for (int i = 0; i < n; i++)
			scanf ("%d", &num[i]);
		scanf ("%d", &target);
		flag = 0;
		memset (vis, 0, sizeof (vis));
		dfs(0, num[0]);
//		printf("%d\n", flag);
		if (!flag)
			printf ("NO EXPRESSION\n");
		else {

			for (int i = 0; i < n; i++) {
				
				if (i == n - 1)
					printf ("%d=%d\n", num[i], target);
				else
					printf ("%d%c", num[i], op[i]);
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值