POJ-1480(最短程序,迭代DFS)

一开始想的是生成一种程序进行一次判断,后来想想,这样基本就减不了枝了,边生成程序边进行操作的话还有可能达到剪枝的效果,于是用了10个stack,用于存放操作数,10个辅助stack,用于操作回滚,然后每生成一条指令,就对10个stack进行一次操作,有一个发生error的时候,就可以剪枝回滚,如果都操作正常,则进行下一条指令的生成,由于还要求在生成程序最短的情况下使得字典序最小,因此在产生指令的时候可以依add->div->dup->mul->sub的顺序进行搜索,这样当发现一个程序满足条件时,一定是最短且字典序最小的:


#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

const char* commands[] = {
	"ADD", "DIV", "DUP", "MUL", "SUB"
};
const int limit = 30000;

int n, x[10], y[10];
vector<int> stack[10], instructions, history[10];

void print()
{
	if(instructions.empty()){
		puts("Empty sequence");
		return;
	}
	printf("%s", commands[instructions[0]]);
	for(int i = 1; i < instructions.size(); ++i) printf(" %s", commands[instructions[i]]);
	puts("");
}
bool add(vector<int>& v, vector<int>& h)
{
	int n = v.size(), r;
	if(n < 2) return false;
	r = v[n-1] + v[n-2];
	if(abs(r) > limit) return false;
	h.push_back(v[n-1]);
	h.push_back(v[n-2]);
	v.pop_back();
	v.back() = r;
	return true;
}
bool div(vector<int>& v, vector<int>& h)
{
	int n = v.size(), r;
	if(n < 2) return false;
	if(v.back() == 0) return false;
	r = v[n-2] / v[n-1];
	if(abs(r) > limit) return false;
	h.push_back(v[n-1]);
	h.push_back(v[n-2]);
	v.pop_back();
	v.back() = r;
	return true;
}
bool dup(vector<int>& v, vector<int>& h)
{
	int n = v.size(), r;
	if(n < 1) return false;
	v.push_back(v.back());
	return true;
}
bool mul(vector<int>& v, vector<int>& h)
{
	int n = v.size(), r;
	if(n < 2) return false;
	r = v[n-1] * v[n-2];
	if(abs(r) > limit) return false;
	h.push_back(v[n-1]);
	h.push_back(v[n-2]);
	v.pop_back();
	v.back() = r;
	return true;
}
bool sub(vector<int>& v, vector<int>& h)
{
	int n = v.size(), r;
	if(n < 2) return false;
	r = v[n-2] - v[n-1];
	if(abs(r) > limit) return false;
	h.push_back(v[n-1]);
	h.push_back(v[n-2]);
	v.pop_back();
	v.back() = r;
	return true;
}
bool simulate(int i, int j)
{
	switch(i){
		case 0: return add(stack[j], history[j]);
		case 1: return div(stack[j], history[j]);
		case 2: return dup(stack[j], history[j]);
		case 3: return mul(stack[j], history[j]);
		default: return sub(stack[j], history[j]);
	}
}
void rewind(int i, int j)
{
	if(i == 2) stack[j].pop_back();
	else{
		stack[j].back() = history[j].back(); history[j].pop_back();
		stack[j].push_back(history[j].back()); history[j].pop_back();
	}
}
bool dfs(int k)
{
	if(!k){
		for(int i = 0; i < n; ++i){
			if(!(stack[i].size() == 1 && stack[i][0] == y[i])) return false;
		}
		return true;
	}

	int i, j;
	for(i = 0; i < 5; ++i){
		for(j = 0; j < n; ++j){
			if(!simulate(i, j)) break;
		}
		if(j < n){
			for(--j; j > -1; --j) rewind(i, j);
			continue;
		}
		instructions.push_back(i);
		if(dfs(k - 1)) return true;
		for(--j; j > -1; --j) rewind(i, j);
		instructions.pop_back();
	}
	return false;
}

int main()
{
	int t = 0, i, j;
	while(scanf("%d", &n), n){
		for(i = 0; i < n; ++i) scanf("%d", x + i);
		for(i = 0; i < n; ++i) scanf("%d", y + i);
		printf("Program %d\n", ++t);
		instructions.clear();
		for(i = 0; i < 11; ++i){
			for(j = 0; j < n; ++j){
				stack[j].clear();
				stack[j].push_back(x[j]);
			}
			if(dfs(i)) break;
		}
		if(i < 11) print(), puts("");
		else puts("Impossible\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值