poj2331 (IDA*)
题意:给你k种管道,然后是每种的长度,每种的数量,求(x1,y1)到(x2,y2)所用管道的最少数量
思路:
最开始考虑的是直接bfs,但是没有成功。
然后发现可以先找x轴x1 到 x2 ,再找y轴y1 到 y2。两个的和便是最终答案。
先用bfs处理出两条轴上的估计函数(即每个地方到x2或y2的距离),然后枚举深度搜索。
Orz;
1.最开始思路的方向就错了,没想到可以x,y轴分开来考虑- -,果然脑子转不过来
2.而且最后忘了判断是否有答案,贡献了个TL
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> typedef long long ll; using namespace std; int len[5]; int num[5]; int have1[1005]; int have2[1005]; int x1,x2,y2,y1,k; void bfs(int *a,int to) //估价函数,到to的最小步数 { queue<int >q; q.push(to); a[to] = 0; while(!q.empty()) { int cur = q.front(); q.pop(); for(int i = 0; i < k; i++) { if(cur-len[i] > 0 && a[cur-len[i]] == -1) { a[cur-len[i]] = a[cur] + 1; q.push(cur-len[i]); } if(cur+len[i]<= 1000 && a[cur+len[i]] == -1) { a[cur+len[i]] = a[cur]+1; q.push(cur+len[i]); } } } } bool IDA(int cur,int now,int ci,int flag) { if(!flag) { if(cur + have1[now] > ci) return false; if(now == x2) //当x轴已经达到目标点x2,去搜索y轴 { if(IDA(0,y1,ci-cur,1)) return true; } } if(flag) { if(cur+have2[now] > ci) return false; if(now == y2) //y轴到达y2点 return true; } for(int i = 0; i < k; i++) { if(num[i] > 0) //还能添加i { num[i]--; if(flag == 0) { if(now + len[i] <= 1000) if(IDA(cur+1,now+len[i],ci,flag)) return true; if(now - len[i] > 0) if(IDA(cur+1,now-len[i],ci,flag)) return true; } else { if(now + len[i] <= 1000) if(IDA(cur+1,now+len[i],ci,flag)) return true; if(now - len[i] > 0) if(IDA(cur+1,now-len[i],ci,flag)) return true; } num[i]++; } } return false; } int main() { while(scanf("%d%d%d%d",&x1,&y1,&x2,&y2) != EOF) { int tmax = 0,ans; scanf("%d",&k); for(int i = 0; i < k; i++) scanf("%d",len+i); for(int i = 0; i < k; i++) { scanf("%d",num+i); tmax += num[i]; } if(x1 == x2 && y1 == y2) { printf("0\n"); continue; } memset(have1,-1,sizeof(have1)); memset(have2,-1,sizeof(have2)); bfs(have1,x2); bfs(have2,y2); for(int i = 0;; i++) { if(IDA(0,x1,i,0)) { ans = i; break; } if(i > tmax){ //找不到答案 ans = 10000; break; } } if(ans <= tmax) printf("%d\n",ans); else printf("-1\n"); } return 0; }