HDU 3681 二分+状压+BFS

来源:互联网 发布:alias vred软件下载 编辑:程序博客网 时间:2024/06/08 04:29

题意

一个人要出逃,需要从F点出发,访问所有的Y点才可以成功出逃,这个人可以拥有一个能量为V的背包,每移动一格消耗1点能量,到达G点的时候可以补充满能量。问最少需要携带一个多小的背包,才能成功出逃。

题解

第一眼看见这道题的时候,想的只是一个普通的BFS。但是在用优先队列实现的时候出现了一些问题,不太好判断优先访问哪个点。倘若不进行优先访问的选择,允许重复访问同一个点,那么无论是时间上还是空间上都是不可承受的。
看了题解才意识到这道题不是一道普通的BFS题,ORZ。。二分背包容量,BFS计算两点之间最短路,状压DP计算某个背包容量是否可行。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define INF 0x3f3f3f3f#define LL long long#define MAXN 8200#define EPS 1e-10#define MOD 100000000using namespace std;struct Node {    int x,y;};char mp[20][20];int vis[20][20];int dis[20][20][20][20];int dp[20][67000];int nodenum;int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};Node nodes[20];int n,m;int finalState;int start;void bfs(int x,int y) {    memset(vis,false,sizeof(vis));    queue<Node> que;    Node first;    first.x=x;    first.y=y;    que.push(first);    dis[first.x][first.y][first.x][first.y]=0;    W(!que.empty()) {        Node front=que.front();        que.pop();        vis[front.x][front.y]=true;        UP(i,0,4) {            Node newnode=front;            newnode.x+=dir[i][0];            newnode.y+=dir[i][1];            if(newnode.x>=n||newnode.y>=m||newnode.x<0||newnode.y<0)                continue;            if(vis[newnode.x][newnode.y])                continue;            if(mp[newnode.x][newnode.y]=='D')                continue;            dis[newnode.x][newnode.y][x][y]=dis[front.x][front.y][x][y]+1;            que.push(newnode);        }    }}bool check(int v) {    memset(dp,-1,sizeof(dp));    dp[start][1<<start]=v;    UP(k,0,1<<nodenum) {        UP(i,0,nodenum) {            if(dp[i][k]==-1||!(k&(1<<i)))                continue;            if((k&finalState)==finalState)                return true;            UP(j,0,nodenum) {                if(i==j||(k&(1<<j)))                    continue;                int cost=dis[nodes[i].x][nodes[i].y][nodes[j].x][nodes[j].y];                if(cost==-1||cost>dp[i][k])                    continue;                dp[j][k+(1<<j)]=max(dp[j][k+(1<<j)],dp[i][k]-cost);                if(mp[nodes[j].x][nodes[j].y]=='G')                    dp[j][k+(1<<j)]=v;            }        }    }    return false;}int main() {    W(~scanf("%d%d",&n,&m)) {        if(n==0&&m==0)            break;        memset(dis,-1,sizeof(dis));        nodenum=0;        finalState=0;        UP(i,0,n) {            scanf("%s",mp[i]);            UP(j,0,m) {                if(mp[i][j]=='F') {                    start=nodenum;                    finalState+=(1<<nodenum);                    nodes[nodenum].x=i;                    nodes[nodenum++].y=j;                }                if(mp[i][j]=='Y') {                    finalState+=(1<<nodenum);                    nodes[nodenum].x=i;                    nodes[nodenum++].y=j;                }                if(mp[i][j]=='G') {                    nodes[nodenum].x=i;                    nodes[nodenum++].y=j;                }            }        }        UP(i,0,nodenum) {            bfs(nodes[i].x,nodes[i].y);        }        int left=0,right=250;        int ans=INF;        W(left<=right) {            int mid=(left+right)/2;            if(check(mid)) {                right=mid-1;                ans=min(ans,mid);            } else {                left=mid+1;            }        }        if(ans==INF) {            puts("-1");        } else {            printf("%d\n",ans);        }    }}/*5 5GDDDSSSDFDSYGDSSGGYSSSYSS1 4FYGY*/
原创粉丝点击