HDU-3502-Huson's Adventure Island(BFS+状压DP)

Problem Description

A few days ago, Tom was tired of all the PC-games, so he went back to some old FC-games. "Hudson‘s Adventure Island" was his favorite which he had played thousands of times. But to his disappointed, the more he played, the more he
lost. Tom soon gave up the game.

Now, he invents an easier game on the base of “Hudson‘s Adventure Island”. He wants to know whether the new game is easy enough. So he came to you for help.

To simplify the problem, you can assume there is matrix-map contains m(0 < m < 256) rows, n(0 < n < 256) columns, an entrance on the top-left corner (0, 0), an exit on the bottom-right corner (m-1, n-1). Each entry of the matrix contains a integer k.The range
of k is defined below:

a)k = 0,it is a free space one can go through.

b)k = -1,it is an obstacle one can’t go through.

c)0 < k < 10000,it is a fruit one can go through and gain k points of energy.

d)k >= 0 at the entrance point and the end point.

At the begin, the hero has 0 points of energy and he can go four directions (up, down, left, right). Each move he makes cost 1 point of energy. No energy no move. If he can’t make a move or get to the exit, he loses the game. The number of fruit is 17 at most.

Input

The input consists of multiple test cases. Each test case starts with two positive integers m, n. Then follows m lines, each line contain n integers.

Output

For each case, if the hero can get the exit, find and print the maximum points of energy he left. Or print “you loss!”

Sample Input

4 4
8 0 0 0
-1 -1 -1 0
-1 -1 -1 0
0 6 0 0
3 3
4 0 0
0 0 0
0 0 0
4 4
5 0 0 0
0 -1 -1 0
0 -1 -1 0
0 0 0 0

Sample Output

4
0
you loss!

Hint

The hero can pass the exit. When he gets the exit point, he can choose to get out to finish the game or move on to gain more points of energy.

Author

imems

Source

2010
ACM-ICPC Multi-University Training Contest(7)——Host by HIT

思路:先用BFS 求出各个水果和终点之间的距离,再用状态压缩DP求解。

#include <cstdio>
#include <queue>
#define INF 999999999
#define max(A,B)(A>B?A:B)
using namespace std;

struct S{
int x,y;
}fruit[20],t;

int n,m,cnt,ans,mp[256][256],dis[20][20],cost[256][256],nxt[4][2]={{1,0},{0,1},{-1,0},{0,-1}},mx[1<<18][20],val[20];

void bfs(S t)
{
    int i,j,nx,ny;

    for(i=0;i<n;i++) for(j=0;j<m;j++) cost[i][j]=INF;

    queue<S>que;

    cost[t.x][t.y]=0;

    que.push(t);

    while(!que.empty())
    {
        t=que.front();

        for(i=0;i<4;i++)
        {
            nx=t.x+nxt[i][0];
            ny=t.y+nxt[i][1];

            if(nx>=0 && nx<n && ny>=0 && ny<m && mp[nx][ny]!=-1 && cost[nx][ny]==INF)
            {
                cost[nx][ny]=cost[t.x][t.y]+1;

                t.x=nx;
                t.y=ny;

                que.push(t);
            }

            t=que.front();
        }

        que.pop();
    }
}

int main()
{
    int i,j;

    while(~scanf("%d%d",&n,&m))
    {
        cnt=0;

        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                scanf("%d",&mp[i][j]);

                if(mp[i][j]>0)
                {
                    fruit[cnt].x=i;
                    fruit[cnt].y=j;

                    val[cnt++]=mp[i][j];
                }
            }
        }

        if(n==1 && m==1)
        {
            if(mp[0][0]>=0) printf("%d\n",mp[0][0]);
            else printf("you loss!\n");

            continue;
        }

        if(mp[0][0]<=0)
        {
            printf("you loss!\n");

            continue;
        }

        if(mp[n-1][m-1]==-1)
        {
            printf("you loss!\n");

            continue;
        }

        fruit[cnt].x=n-1;//终点也放进去
        fruit[cnt].y=m-1;

        for(i=0;i<=cnt;i++)
        {
            bfs(fruit[i]);

            for(j=0;j<=cnt;j++) dis[i][j]=cost[fruit[j].x][fruit[j].y];//各个水果和终点之间的距离

        }

        queue<S>que;

        for(i=1;i<(1<<cnt);i++) for(j=0;j<cnt;j++) mx[i][j]=-1;

        int v;

        t.x=1;
        t.y=0;

        mx[t.x][t.y]=val[0];

        que.push(t);

        while(!que.empty())
        {
            t=que.front();

            for(i=1;i<cnt;i++)
            {
                if(!(t.x & (1<<i)))
                {
                    v=mx[t.x][t.y]-dis[t.y][i];

                    if(v>=0)
                    {
                        t.x=(t.x | (1<<i));
                        t.y=i;

                        if(v+val[i]>mx[t.x][i])
                        {
                            mx[t.x][i]=v+val[i];
                            que.push(t);
                        }

                        t=que.front();
                    }
                }
            }

            que.pop();
        }

        ans=-1;

        for(i=1;i<(1<<cnt);i++) for(j=0;j<cnt;j++) ans=max(ans,mx[i][j]-dis[j][cnt]);

        if(ans>=0) printf("%d\n",ans);
        else puts("you loss!");
    }
}

HDU-3502-Huson's Adventure Island(BFS+状压DP)

时间: 2024-10-11 12:31:50

HDU-3502-Huson's Adventure Island(BFS+状压DP)的相关文章

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using

hdu 5135 Little Zu Chongzhi&#39;s Triangles 状压DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5135 从大到小贪心是不对的! 比如 4 30 40 50 89 这组数据 结果应该是600 如果取后三条边只会是一个细长细长的三角形根本没多大面积 只不过因为数据水然后贪心碰巧能过而已 看到网上题解很多人用贪心我好郁闷... 状压DP 看到边的数目很少就应该想到这个了 先枚举可能出现的所有三角形 记录他们使用了那些边还有他们的面积 然后再枚举状态之中 套一层遍历所有三角形的循环 如果当前状态和三角形

HDU 5131 Little Zu Chongzhi&#39;s Triangles (状压DP +2014广州现场赛)

题目链接:HDU 5131 Little Zu Chongzhi's Triangles 题意:给出一些线段,在其中选出3根组成三角形,问用这些线段组成的所有三角形的最大面积是多少. 7 3 4 5 3 4 5 90 两个三角形是(3,3,4),(5,5,4). 思路:N最大12,状态压缩,把所有可能组成的三角形存起来.A&B==0则说明A|B状态是有效的. 贪心也能过..为什么? AC代码: #include <stdio.h> #include <string.h> #

HDU 3920Clear All of Them I(状压DP)

HDU 3920   Clear All of Them I 题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人,问最少花费是多少(反正题意大概就是这样啦,知道怎么回事就好了,解释不清了) 一看到n<=10而且又是在DP专题里的,就知道这个显然是状压DP,由于有2n个敌人,所以状态表示由当前状态再打两个人来转移, 10000100表示打了这两个敌人的最小花费 所以状态的转移是由前往后递推的,假如当前状态是cu

HDU 5135 Little Zu Chongzhi&#39;s Triangles(状压dp或者贪心)

题目大意:给你n个线段让你任意组成三角形,求组出来的三角形的面积的和最大为多少. 解题思路:首先你得知道海伦公式:S = sqrt(p*(p-a)*(p-b)*(p-c)), p = (a+b+c)/2. 思路一:贪心,按照边的长度进行排序,从大到小判断如果可以构成三角形,就让他构成三角形,这样组成的三角形的面积和一定是最大的. 思路二:状压dp,先暴力求出来所有可以组成的三角形对应的状态和面积,然后dp求解,状态转移公式是:dp[i|(f[j].xnum)] = max(dp[i|(f[j].

HDU 3681 BFS&amp;状压DP&amp;二分

N*M矩阵,从F点出发,走完所有的Y点,每走一格花费1点电量,走到G点时,电量充满,D不可到达,问起始时的最小满电量可以走完所有Y,Y和G一共最多15个 先BFS出所有的F,Y,G之间的最短距离. 然后二分起始电量,对每个电量,做状压DP判断是否可行 #include "stdio.h" #include "string.h" #include "queue" using namespace std; int inf=0x3f3f3f3f; in

HDU 5067 Harry And Dig Machine(状压dp)

HDU 5067 Harry And Dig Machine 思路:由于点才10个,在加上一个起点,处理出每个点之间的曼哈顿距离,然后用状压dp搞,状态表示为: dp[i][s],表示在i位置,走过的点集合为s的最小代价 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int N = 15;

HDU-4856 Tunnels (BFS+状压DP)

Problem Description Bob is travelling in Xi’an. He finds many secret tunnels beneath the city. In his eyes, the city is a grid. He can’t enter a grid with a barrier. In one minute, he can move into an adjacent grid with no barrier. Bob is full of cur

POJ 2688 BFS+状压DP

标准的TSP问题 m*n矩阵,有不超过10个需要走到的点,给出起点,问走最少的步子把所有点走完 BFS出每个必须走到的点的最短距离 然后状压DP即可 #include "stdio.h" #include "string.h" #include "queue" using namespace std; const int dir[4][2]={ {1,0},{-1,0},{0,1},{0,-1} }; int inf=0x7fffffff; in