用最少的管子数,连接平面上的两点,只允许横放或竖放,允许交叉或重叠
方法:先搜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;
}