可怕的bug codeup 问题 E: 【宽搜入门】巧妙取量

3 篇文章 0 订阅
3 篇文章 0 订阅

题目链接:http://codeup.cn/problem.php?cid=100000609&pid=4

吐槽

实在是太口怕了,一个上午才做2道题,debug使我疯狂

注意点
  1. 考虑使用map来映射
  2. abc三个桶的状态构成一个整数,表示这种状态,要求这个数是能独一无二代表某种状态
    最初使用tmpNum = st.a * 100 + st.b * 10 + st.c;
    问题就出在这种表示方法上,题目给出的每个桶的容积abc,对于这三个数,每个数最少1位,最多3位,若是采用上面的方法,只是进⑩,很有可能出现两种不同的状态,使得两个状态得到同一个整数
    比如对于起始状态100 0 0 某一个中间状态为50 20 30,得到的整数是5230,但是5230对应的状态总共有4种!
    tmpNum 	a  		b		c
    5230    48      42      10
    5230    49      31      20
    5230    50      20      30
    5230    51      9       40
    
  3. 采用新的表示方法:每个数占3位,最多9位,还在int范围内(<abs(2*109))
    tmpNum = st.a * 1000000 + st.b * 1000 + st.c;
代码
#include <iostream>
#include <queue>
#include <unordered_map>
#include <cstring>
using namespace std;

struct Node {
	int a, b, c, step;
};
int ca, cb, cc, k;

// 1 a->b   2  b->a
// 3 a->c   4  c->a
// 5 b->c   6  c->b
bool judge(Node top,int way) {
	
	int a = top.a;
	int b = top.b;
	int c = top.c;
	
	if ((way == 1) && (a <= 0 || b >= cb))
		return false;
	if ((way == 2) && (b <= 0 || a >= ca))
		return false;
	if ((way == 3) && (a <= 0 || c >= cc))
		return false;
	if ((way == 4) && (c <= 0 || a >= ca))
		return false;
	if ((way == 5) && (b <= 0 || c >= cc))
		return false;
	if ((way == 6) && (c <= 0 || b >= cb))
		return false;

	return true;
}

void f(int& a, int& b,const int xb) {
	if (a + b > xb) {
		a = a + b - xb;
		b = xb;
	} else {
		b = a + b;
		a = 0;
	}
}

// 1 a->b   2  b->a
// 3 a->c   4  c->a
// 5 b->c   6  c->b
Node dosomething(Node top, int way) {
	
	int a = top.a;
	int b = top.b;
	int c = top.c;

	if (way == 1)	f(a, b,cb);
	if (way == 2)	f(b,a,ca);
	if (way == 3)	f(a, c,cc);
	if (way == 4)	f(c,a,ca);
	if (way == 5)	f(b,c,cc);
	if (way == 6)	f(c,b,cb);

	Node node;
	node.a = a;
	node.b = b;
	node.c = c;
	node.step = top.step + 1;
	return node;
}

queue<Node> q;
unordered_map<int,bool> mp;
//const int maxn = 150;
//int a[maxn][maxn][maxn] = { 0 };
int BFS(Node st) {
	
	mp.clear();
	//memset(a, 0, sizeof(a));
	while (!q.empty()) {
		q.pop();
	}
	q.push(st);
	int tmpNum = st.a * 1000000 + st.b * 1000 + st.c;
	mp[tmpNum] = true;
	//a[st.a][st.b][st.c] = 1;

	while (!q.empty()) {
		Node top = q.front();
		q.pop();
		if (top.a == k || top.b == k || top.c == k)
			return top.step;
		// 6种操作
		for (int way = 1; way <= 6; way++) {
			if (judge(top, way)) {
				Node newNode = dosomething(top, way);
				int tmpNum2 = newNode.a * 1000000 + newNode.b * 1000 + newNode.c;
				if (mp[tmpNum2] == false)
					//if (a[newNode.a][newNode.b][newNode.c] == 0)
				{
					q.push(newNode);
					mp[tmpNum2] = true;
					//a[newNode.a][newNode.b][newNode.c] = 1;
				}
			}
		}
	}
	return -1;
}


int main() {
	while (scanf("%d%d%d%d",&ca,&cb,&cc,&k)!=EOF) {
		Node st = { ca,0,0,0 };
		int step = BFS(st);
		if (step != -1) {
			printf("yes\n%d\n", step);
		} else {
			printf("no\n");
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值