24点 - DFS

Time Limit:1000ms          Memory Limit: 65535KB

在Jason生活的星球上,算术学期末总是考同样的题目:抽四张扑克牌,在1秒内通过四则运算让其结果为24。

但是Jason的算术太拙了,总是没办法在1秒内得到正确答案。期末考试就快要到了,但正直的Jason不想靠命运力神抽4张6来通过考试。

你能为Jason设计一个24点的算法,好让他不挂科吗?

输入:

给定一个提示输入行,让监考老师输入四个正整数 (均小于INT_MAX)

输出:

如果能够算出24,打印一个由输入数字组成的结果为24的四则运算算式,用括号表明优先级

否则输出一个"You WIN!"

例子:

Input

请输入四张牌的点数:

6 6 6 6

Output

((6+6)+6)+6=24


...

(以上纯属瞎说)

四个数字的所有排列组合有4! == 24种,三个运算符的运算次序有3! == 6种(实际上只有5种,因为1->3->2 和3->1->2 得到的结果是一样的),这个规模完全可以用穷举来做

可以考虑用穷举+深度优先算法来解决这个问题。

首先要能够将四个数字的全部排列组合,由于每个对于(n+1)个数的排列组合其实由第(n+1)个数与前n个数的全排列中每个数位分别交换,加上处于第(n+1)个数位上的情况得到,这位穷举排列提供了思路,也就是输入两个参数a和b,循环地将card[a]和a~b之间每个数交换,交换后对a后面作全排列。

在每次排列列举结束时,a就大于b,这时将这一排列进行完全四则运算,如果得到结果就打印出来。


#include 
#include 
using namespace std;
int card[4];

bool DFS(int,int);
bool full_cal();
double arith_cal(double, double, int);
char oprt(int);

int main()
{
	do
	{
		printf("请输入四张牌的点数:\n");
		scanf("%d %d %d %d", card, card + 1, card + 2, card + 3);
		if (!DFS(0, 3))
			printf("You WIN!\n");
	} while (getchar() != 'q');
	return 0;
}

bool DFS(int a, int b)
{
	if (a > b)   //如果左标a大于b,说明上一次交换已经达到了b与b交换,深度到底,这时可以将此排列作完全四则运算
	{
		if (full_cal())
			return 1;
	}
	else
	{
		for (int i = a; i <= b; i++)
		{
			swap(card[a], card[i]);  //交换第i个与第a个数
			if (DFS(a + 1, b))       //运算a后面几个数
				return 1;
			swap(card[a], card[i]);  //换回来,为之后的运算提供基础
		}
	}
	return 0;
}

bool full_cal()
{
	double a = (double)card[0];      //考虑可能的分数运算 用double存储
	double b = (double)card[1];
	double c = (double)card[2];
	double d = (double)card[3];

	int i, j, k, l;                  //i控制运算顺序,j、k、l控制运算符
	for (i = 0; i<5; i++)
		for (j = 0; j<4; j++)
			for (k = 0; k<4; k++)
				for (l = 0; l<4; l++)
				{
					switch (i)
					{
					case 0:
						if (arith_cal(arith_cal(arith_cal(a, b, j), c, k), d, l) == 24)
						{
							printf("((%d%c%d)%c%d)%c%d=24\n", card[0], oprt(j), card[1], oprt(k), card[2], oprt(l), card[3]);
							return 1;
						}
					case 1:
						if (arith_cal(arith_cal(a, b, j), arith_cal(c, d, l), k) == 24)
						{
							printf("(%d%c%d)%c(%d%c%d)=24\n", card[0], oprt(j), card[1], oprt(k), card[2], oprt(l), card[3]);
							return 1;
						}
					case 2:
						if (arith_cal(arith_cal(a, arith_cal(b, c, k), j), d, l) == 24)
						{
							printf("(%d%c(%d%c%d))%c%d=24\n", card[0], oprt(j), card[1], oprt(k), card[2], oprt(l), card[3]);
							return 1;
						}
					case 3:
						if (arith_cal(a, arith_cal(arith_cal(b, c, k), d, l), j) == 24)
						{
							printf("%d%c((%d%c%d)%c%d)=24\n", card[0], oprt(j), card[1], oprt(k), card[2], oprt(l), card[3]);
							return 1;
						}
					case 4:
						if (arith_cal(a, arith_cal(b, arith_cal(c, d, l), k), j) == 24)
						{
							printf("%d%c(%d%c%(%d%c%d))=24\n", card[0], oprt(j), card[1], oprt(k), card[2], oprt(l), card[3]);
							return 1;
						}
					}
				}
	return 0;
}

double arith_cal(double a, double b, int i)
{
	switch (i)
	{
	case 0:
		return a + b;
	case 1:
		return a - b;
	case 2:
		return a*b;
	case 3:
		if (b == 0)        //除数为0时返回一个-1,让结果肯定不等于24
			return -1;
		else
			return a / b;
	}
}

char oprt(int p)
{
	switch (p)
	{
	case 0:
		return '+';
	case 1:
		return '-';
	case 2:
		return '*';
	case 3:
		return '/';
	}
}







你可能感兴趣的:(C/C++,课程学习报告)