UVa 10344 - 23 out of 5 递归回溯

Problem I

23 Out of 5

Input: standard input

Output: standard output

Time Limit: 1 second

Memory Limit: 32 MB

Your task is to write a program that can decide whether you can find an arithmetic expression consisting of five given numbers (1<=i<=5) that will yield the value 23.
For this problem we will only consider arithmetic expressions of the following from:

 
where : {1,2,3,4,5} -> {1,2,3,4,5} is a bijective function
and  {+,-,*} (1<=i<=4)

Input

The Input consists of 5-Tupels of positive Integers, each between 1 and 50.
Input is terminated by a line containing five zero's. This line should not be processed.

Output

For each 5-Tupel print "Possible" (without quotes) if their exists an arithmetic expression (as described above) that yields 23. Otherwise print "Impossible".

Sample Input

1 1 1 1 1
1 2 3 4 5
2 3 5 7 11
0 0 0 0 0

Sample Output

Impossible
Possible
Possible

Thomas Strohmann


译文:

你的任務是寫一個程式,看看是否能在5個數字間插入一些運算子使得結果為23。

考慮以下的運算式結果是否可能等於23。

(((a1 O1 a2) O2 a3) O3 a4) O4 a5

在這裡a1~a5為5個給你的整數(順序可以隨便排列,但一定都要出現一次),O1~O4為運算子,內容為{+,-,*}其中一個。如果你還不清楚的話,以下面的例子來說明:

輸入5個整數2,3,5,711
你可以找到有一組運算式 (((11*3)-5)+2)-7=23,所以輸出Possible。(當然,可以得到23的答案的運算式可能不只一組)

若輸入的5個整數為1,1,1,1,1
那你就找不到任一種運算式的組合可以使答案為23。所以輸出Impossible。

Input

每一測試資料一列,有5個整數。每個整數均介於0到50之間。當輸入為5個0時代表輸入結束。測試資料總共不會超過25列。

Output

根據輸入的5個整數,判斷是否可能找到使其答案為23的運算式。請參考Sample Output



#include <iostream>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <algorithm>
using namespace std;

int num[5];
int vis[5];

char flag2[3]={'+','-','*'};
int vis2[3];

int temp[5];
char calSignal[4];
bool ans=false;

void init()
{
	ans = false;
	memset(num, 0, sizeof(num));
	memset(vis, 0, sizeof(vis));
	memset(vis2, 0, sizeof(vis2));
}

bool cal()
{
	int value=0;
	for(int i=0; i < 4; i++)
	{
		switch(calSignal[i])
		{
			case '+': {
				if(i==0)
					value = temp[i]+temp[i+1];
				else 
					value += temp[i+1];
				break;
			}
			case '-': {
				if(i==0)
					value = temp[i]-temp[i+1];
				else 
					value -= temp[i+1];
				break;
			}
			case '*':{
				if(i==0)
					value = temp[i]*temp[i+1];
				else 
					value *= temp[i+1];
				break;
			}	
		}
	}	
	if(value==23 || value==-23)
		return true;
	return false;
}
// 同时遍历两种可能性 TLE 
void f(int number, int signal)
{
	if(ans) return ;
	if(number==4 && signal==3)
	{
		if(cal())
			ans = true;
		return ;
	}		
	for(int i=0; i < 5; i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			temp[number] = num[i];
			f(number+1, signal);
			vis[i]=0;
		}
	}
	for(int i=0; i < 3; i++)
	{
		if(!vis2[i])
		{
			vis2[i]=1;
			calSignal[signal] = flag2[i];
			f(number, signal+1);
			vis2[i] = 0;
		}
	}
}

void dfs(int length, int sum)
{
	if(length==5)
	{
		if(sum==23)
			ans = true;
		return ;
	}
	sum += num[length];
	dfs(length+1, sum);
	sum -= num[length];
	if(ans) return;
	
	sum -= num[length];
	dfs(length+1, sum);
	sum += num[length];
	if(ans) return;
	
	sum *= num[length];
	dfs(length+1, sum);
	sum /= num[length];
	if(ans) return ;
}

void solve()
{
	sort(num, num+5);
	do{
		
		dfs(1, num[0]);
		if(ans)
			return ;
		
	}while(next_permutation(num, num+5));
}

bool read()
{
	for(int i=0; i < 5; i++)
	{
		cin >> num[i];
		if(num[i]==0) return false;
	}
	return true;
}

int main()
{
//	freopen("in.txt","r",stdin);
	while(1)
	{
		init();
		bool flag = read();
		if(flag)
		{
			solve(); 
			if(ans)
				cout << "Possible" << endl;
			else
				cout << "Impossible" << endl;
		}else	
			break;				
	}
//	printf("%.2lf\n", (double)clock()/CLOCKS_PER_SEC);
	return 0;
} 

全排列+DFS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值