poj 2331

(IDA*: 即为A*算法加上迭代加深搜索,本题为IDA*)


Description

The Eastowner city is perpetually haunted with water supply shortages, so in order to remedy this problem a new water-pipe has been built. Builders started the pipe from both ends simultaneously, and after some hard work both halves were connected. Well, almost. First half of pipe ended at a point (x1, y1), and the second half -- at (x2, y2). Unfortunately only few pipe segments of different length were left. Moreover, due to the peculiarities of local technology the pipes can only be put in either north-south or east-west direction, and be connected to form a straight line or 90 degree turn. You program must, given L1, L2, ... Lk -- lengths of pipe segments available and C1, C2, ... Ck -- number of segments of each length, construct a water pipe connecting given points, or declare that it is impossible. Program must output the minimum required number of segments.

Constraints
1 <= k <= 4, 1 <= xi, yi, Li <= 1000, 1 <= Ci <= 10

Input

Input contains integers x1 y1 x2 y2 k followed by 2k integers L1 L2 ... Lk C1 C2 ... Ck

Output

Output must contain a single integer -- the number of required segments, or −1 if the connection is impossible.

Sample Input

20 10 60 50 2 70 30 2 2

Sample Output

4








我的IDA*算法的第一题^-^...

它与bfs不同的地方是前面多用的一个“限制”,在本题中,既是先不管水管的个数,假设所有水管无限多。分别看横纵坐标从终点倒着走到(一维,因为横纵坐标分别考虑)每个点所需的步数。然后利用这个进行迭代加深搜索(枚举答案)与大幅度剪枝.

具体细节见代码:

<span style="color:#000000;">#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

#define MAXN (1000+5)

struct node{
	int l, c;
};

int n, ans;
int sx, sy, tx, ty;
node pipe[11];
int hx[MAXN], hy[MAXN];

void bfs(int *h, int x){
	queue<int> q;
	h[x] = 0;
	q.push(x);

	while(!q.empty()){
		int now = q.front(); q.pop();

		for(int i = 1; i <= n; i++){
			int len = pipe[i].l;

			if(now-len >= 1 && h[now-len] == -1){
				h[now-len] = h[now]+1;
				q.push(now-len);
			}
			if(now+len <= 1000 && h[now+len] == -1){
				h[now+len] = h[now]+1;
				q.push(now+len);
			}
		}
	}
}

bool check(node *a, int x, int dep, int k){
	int hv = k? hy[x]: hx[x];
	if(hv+dep > ans || hv == -1) return false;

	if(!hv){
		if(!k) return check(a, sy, dep, 1);
		else return true;
	}

	node tmp[11];
	for(int i = 1; i <= n; i++) tmp[i] = a[i];
	
	for(int i = 1; i <= n; i++)
	    if(tmp[i].c){
			tmp[i].c--;
			if((x-tmp[i].l)>=1 && check(tmp, x-tmp[i].l, dep+1, k)) return true;
			if((x+tmp[i].l)>=1 && check(tmp, x+tmp[i].l, dep+1, k)) return true;
			tmp[i].c++;
		}

	return false;
}

int main(){
	scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
	
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &pipe[i].l);

	int num = 0;
	for(int i = 1; i <= n; i++){
		scanf("%d", &pipe[i].c);
		num += pipe[i].c;
	}

	memset(hx, -1, sizeof(hx));
	memset(hy, -1, sizeof(hy));
	bfs(hx, tx);
	bfs(hy, ty);

	for(ans = 1; ans <= num; ans++)
	  if(check(pipe, sx, 0, 0)) break;

	if(ans <= num) printf("%d\n", ans);
	else printf("-1\n");
	
	return 0;
}</span>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值