poj2331 ida*

用最少的管子数,连接平面上的两点,只允许横放或竖放,允许交叉或重叠

方法:先搜x轴,再搜y轴

预处理估价函数

还是觉得很唯美~

#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
struct data {
       int l,num;
}a[10];
int n,sx,sy,tx,ty,h1[1010],h2[1010],total,ans;
void cal(int *h,int pos) {
     queue<int> q;
     h[pos] = 0;
     q.push(pos);
     while (!q.empty()) {
           pos = q.front();
           q.pop();
           for (int i=1;i<=n;i++) {
               if (pos-a[i].l>=1 && h[pos-a[i].l]==-1) {
                                 h[pos-a[i].l] = h[pos] + 1;
                                 q.push(pos-a[i].l);
               }
               if (pos+a[i].l<=1000 && h[pos+a[i].l]==-1) {
                                 h[pos+a[i].l] = h[pos] + 1;
                                 q.push(pos+a[i].l);
               }
           }
     }
}
bool dfs(data *a,int x,int dep,int type) {
    int hv; 
    if (type==0) hv = h1[x]; else hv = h2[x];
    if (hv==-1 || hv + dep > ans) return false;
    if (hv==0) {
               if (type==0) return dfs(a,sy,dep,1);
               else return true;
    }
    data tmp[10];
    for (int i=1;i<=n;i++)
        tmp[i]= a[i];
    for (int i=1;i<=n;i++)
        if (tmp[i].num > 0) {
                       tmp[i].num--;
                       if (type==0) {
                          if (x-tmp[i].l > 0) if (dfs(tmp,x-tmp[i].l,dep+1,0)) return true;
                          if (x+tmp[i].l <= 1000) if (dfs(tmp,x+tmp[i].l,dep+1,0)) return true;
                       } else {
                         if (x+tmp[i].l <= 1000) if (dfs(tmp,x+tmp[i].l,dep+1,1)) return true;
                         if (x-tmp[i].l > 0) if (dfs(tmp,x-tmp[i].l,dep+1,1)) return true;
                       }         
                       tmp[i].num++;
        }
    return false;
}
void ida_star() {
    memset(h1,-1,sizeof(h1));
    memset(h2,-1,sizeof(h2));
    cal(h1,tx);
    cal(h2,ty);
     
	for (ans=1;ans<=total;ans++)
	    if (dfs(a,sx,0,0)) break;
	if (ans<=total) printf("%d\n",ans);
    else printf("-1\n"); 
}
int main() {
	scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
	scanf("%d",&n);
	total = 0;
    for (int i=1;i<=n;i++)
		scanf("%d",&a[i].l);
	for (int i=1;i<=n;i++) {
		scanf("%d",&a[i].num);
		total+=a[i].num;
    }

	if (sx==tx && sy==ty) printf("0\n");
	else ida_star();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值