#POJ2331#Water pipe(IDA*_搜索)

13 篇文章 0 订阅
9 篇文章 0 订阅

Water pipe
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 2508 Accepted: 715

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

题意:

给出K种长度的水管,并告诉每种长度有多少根,要求用这些水管从(x1,y1)一直铺到(x2,y2),最少使用多少根水管,水管可以交叉。

注意水管铺的范围坐标在0 ~ 1000


剪枝很重要,H值得设置如下:

假设现在只考虑一个坐标,那么BFS计算出可能到达的所有单个坐标的最少管道数量,

而对于当前的点x,y,它到达终点的管道数量,一定能保证大于等于Bfs单座标数+当前数,


Code:

Status Accepted
Time 641ms
Memory 744kB
Length 2111
Lang G++
Submitted
Shared
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int Max = 6;

bool flg;
int K, lim, sum;
int x1, y1, x2, y2;
int L[Max], C[Max], H1[1005], H2[1005];
int dd[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

void getint(int & num){
    char c; int flg = 1;    num = 0;
    while((c = getchar()) < '0' || c > '9') if(c == '-')    flg = -1;
    while(c >= '0' && c <= '9'){    num = num * 10 + c - 48;    c = getchar(); }
    num *= flg;
}

int Bfs_H(int * H, int s){
    queue<int>Q;
    H[s] = 0;
    Q.push(s);
    while(! Q.empty()){
        int tmp = Q.front();    Q.pop();
        for(int i = 1; i <= K; ++ i){
            int x = tmp - L[i];
            if(x > 0 && H[x] == -1)
                H[x] = H[tmp] + 1,
                Q.push(x);
            x += (L[i] << 1);
            if(x <= 1000 && H[x] == -1)
                H[x] = H[tmp] + 1,
                Q.push(x);
        }
    }
}

void Dfs(int x, int y, int now, int *state){
    if(now > lim)   return ;
    if(x == x2 && y == y2){flg = 1; return ;}
    if(now + H1[x] > lim || now + H2[y] > lim) return ;
    int newstate[Max];
    memcpy(newstate, state, sizeof newstate);
    for(int i = 1; i <= K; ++ i)    if(newstate[i]){
        -- newstate[i];
        for(int j = 0; j < 4; ++ j){
            int xx = x + L[i] * dd[j][0];
            int yy = y + L[i] * dd[j][1];
            if(xx >= 0 && yy >= 0 && xx <= 1000 && yy <= 1000)
                Dfs(xx, yy, now + 1, newstate);
            if(flg) return ;
        }
        ++ newstate[i];
    }
}

int main(){
    getint(x1), getint(y1), getint(x2), getint(y2);
    getint(K);
    for(int i = 1; i <= K; ++ i)    getint(L[i]);
    for(int i = 1; i <= K; ++ i)    getint(C[i]), sum += C[i];
    if(x1 == x2 && y1 == y2){puts("0"); return 0;}
    memset(H1, -1, sizeof H1 );
    memset(H2, -1, sizeof H2 );
    Bfs_H(H1, x2);
    Bfs_H(H2, y2);
    for(lim = 1; lim <= sum; ++ lim){
        Dfs(x1, y1, 0, C);
        if(flg) break;
    }
    if(flg) printf("%d\n", lim);
    else puts("-1");
    return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值