hdu Collect More Jewels

思路:

先用bfs求出入口,宝物,出口,两两之间的最短距离。

在用dfs搜索所有情况,求出从入口走到出口能获得的最大价值。

我们要解决几个问题:1、求入口到第一个取宝物的地方的最短距离

2、求第i个取宝物的地方到第i+1个取宝物的地方的最短距离

3、求第n个取宝物的地方到出口的最短距离

4、保证以上3点能在时间L内实现的情况下,取得的宝石价值最大

熟悉两种搜索的优缺点:

BFS: 对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。

DFS:对于解决遍历求和问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高

dfs剪枝:

1.step>time直接return。

2.ans==sum时就不用再搜了  因为已经到最大了。

3.如果搜到一个点,这个点以前已经搜过,而且现在到达这个点时珠宝价值比以前少而且走的步数却比以前多,就不用搜这个点了。

真是被自己傻到了 。。。花了一个小时写了一个代码如下,感觉自己真是太弱智了,居然放这么大的错误,忽略了两件宝物可以在一条路径上,所以 以后编程还是要考虑周全在下手 ,尤其是比赛的时候,一旦有大的漏洞,就会被 坑哭了。。。

错误代码:

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"cmath"
#include"string"
#include"string.h"
#include"queue"
#include"stack"
#include"vector"
#define  mx 105
using namespace std;
int  g[mx][mx];
int value[mx][mx];//存放每个点的价值
int time[mx][mx];//存放每个点的时间
int M[mx];//存放宝物的价值
int h,w,m,l,sx,sy,ex,ey,maxvalue;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct node
{
    int x,y;
    int times;
    int  values;
};
bool judge1(int x,int y)//判断能不能走
{
    if(x>=0&&x<h&&y>=0&&y<w&&g[x][y]!=-1)
        return true;
    return false;
}
bool judge2(int x,int y,int v,int t)//判断应不应该走
{
    if(v>value[x][y]) return true;
    if(t<time[x][y]) return true;
    return false;
}
void bfs()
{
    queue<node>q;
    node cur,next;
    int i;
    cur.x=sx;cur.y=sy;cur.times=0;cur.values=0;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        if(cur.x==ex&&cur.y==ey&&cur.times<=l)
        {
            if(maxvalue<cur.values) maxvalue=cur.values;
        }
        for(i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            if(judge1(next.x,next.y))
            {
                next.times=cur.times+1;
                next.values=cur.values+g[next.x][next.y];
                if(judge2(next.x,next.y,next.values,next.times))
                {
                  q.push(next);
                  time[next.x][next.y]=next.times;
                  value[next.x][next.y]=next.values;
                  g[next.x][next.y]=0;
                }
            }
        }
    }
}
int main()
{
    int i,j,t,cou=0;;
    char ch;
    cin>>t;
    while(t--)
    {
        cou++;
        cin>>w>>h>>l>>m;
        for(i=0;i<m;i++) cin>>M[i];
        getchar();
        for(i=0;i<h;i++)
        {
            for(j=0;j<w;j++)
            {
                cin>>ch;
                switch(ch)
                {
                    case ‘*‘:g[i][j]=-1;break;
                    case ‘.‘:g[i][j]=0;break;
                    case ‘@‘:g[i][j]=0;sx=i;sy=j;break;
                    case ‘<‘:g[i][j]=0;ex=i;ey=j;break;
                    default: g[i][j]=M[ch-‘0‘-65];break;
                }
            }
        }
        memset(value,0,sizeof(value));
        for(i=0;i<h;i++)
            for(j=0;j<w;j++) time[i][j]=1000001;
        maxvalue=-1;
        bfs();
        cout<<"Case "<<cou<<":"<<endl;
        if(maxvalue>=0)
            cout<<"The best score is "<<maxvalue<<"."<<endl<<endl;
        else cout<<"Impossible"<<endl<<endl;
    }
    return 0;
}

在网上搜了一下别人的代码,大致就是先利用bfs构建一个隐氏图,然后再用dfs进行搜索,找到最大价值总和。

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"cmath"
#include"string.h"
#include"string"
#include"queue"
#define mx 105
using namespace std;
char mp[mx][mx];
bool used[mx][mx];//标记bfs走过的路径
bool vis[mx];//标记 dfs走过的路径
int value[mx];//记录宝物的价值
int H,W,L,M,ans,sum;
int step[mx][mx];//记录每个位置的最小步骤
int dis[mx][mx];//记录出口、入口、宝物两两之间的最短距离
queue<int>q;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
bool judge(int x,int y)//判断该位置是否可走
{
    if(x>=0&&x<H&&y>=0&&y<W&&mp[x][y]!=‘*‘) return true;
    return false;
}
void bfs(int x1,int y1,int s)
{
    while(!q.empty()) q.pop();
    int dx,dy,i,u,x,y;
    memset(used,false,sizeof(used));
    memset(step,0,sizeof(step));
    u=x1*W+y1;
    q.push(u);
    used[x1][y1]=true;
    step[x1][y1]=0;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        x=u/W;
        y=u%W;
        for(i=0;i<4;i++)
        {
            dx=x+dir[i][0];
            dy=y+dir[i][1];
            if(judge(dx,dy))
            {
                if(!used[dx][dy])
                {
                    used[dx][dy]=true;
                    step[dx][dy]=step[x][y]+1;
                    if(mp[dx][dy]==‘@‘)
                        dis[s][0]=step[dx][dy];
                    else if(mp[dx][dy]==‘<‘)
                        dis[s][M+1]=step[dx][dy];
                    else if(mp[dx][dy]>=‘A‘&&mp[dx][dy]<=‘J‘)
                        dis[s][mp[dx][dy]-‘A‘+1]=step[dx][dy];
                    q.push(dx*W+dy);
                }
            }
        }
    }
}
void dfs(int s,int val,int time)
{
    int i;
    if(time>L) return;
    if(ans==sum) return;
    if(s>M)
    {
        if(val>ans)ans=val;
        return;
    }
    for(i=0;i<=M+1;i++)
    {
        if(dis[s][i]==0||vis[i]) continue;
        vis[i]=true;
        dfs(i,value[i]+val,time+dis[s][i]);
        vis[i]=false;
    }
}
int main()
{
    int i,j,t,icase=0;
    cin>>t;
    while(t--)
    {
        sum=0;ans=-1;
        memset(dis,0,sizeof(dis));//记得初始化dis
        icase++;
        cin>>W>>H>>L>>M;
        for(i=1;i<=M;i++) {cin>>value[i];sum+=value[i];}
        for(i=0;i<H;i++) cin>>mp[i];
        value[0]=0;value[M+1]=0;
        for(i=0;i<H;i++)
        {
            for(j=0;j<W;j++)
            {
                if(mp[i][j]==‘@‘) bfs(i,j,0);
                else if(mp[i][j]==‘<‘)bfs(i,j,M+1);
                else if(mp[i][j]>=‘A‘&&mp[i][j]<=‘J‘) bfs(i,j,mp[i][j]-‘A‘+1);
            }
        }
        memset(vis,false,sizeof(vis));
        vis[0]=true;
        dfs(0,0,0);
        cout<<"Case "<<icase<<":"<<endl;
        if(ans>0)
            cout<<"The best score is "<<ans<<"."<<endl;
        else  cout<<"Impossible"<<endl;
        if(t) cout<<endl;
    }
}

时间: 2024-10-13 07:06:45

hdu Collect More Jewels的相关文章

HDU Collect More Jewels 1044

BFS + 状态压缩 险过 这个并不是最好的算法 但是写起来比较简单 , 可以AC,但是耗时比较多 下面是代码 就不多说了 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define Max(a,b) (a>b?a:b) #define Min(a,b) (a

HDU 1044 Collect More Jewels 【经典BFS+DFS】

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6597    Accepted Submission(s): 1527 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

HDU 1044 Collect More Jewels【BFS+DFS+建立距离图】

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6707    Accepted Submission(s): 1556 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

hdu.1044.Collect More Jewels(bfs + 状态压缩)

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5345    Accepted Submission(s): 1189 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

Collect More Jewels(hdu1044)(BFS+DFS)

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6857    Accepted Submission(s): 1592 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

hdu 1044 Collect More Jewels

并没有做过这种类型的题目,不太会做...看了一下大神的代码,然后自己敲...额..思路一样了,代码也差不多.. http://www.cnblogs.com/kuangbin/archive/2012/08/14/2637512.html 先通过BFS预处理任意两点之间的距离,然后通过DFS暴力模拟路径,算出最优解. 感觉自己可能对BFS理解比DFS更深一点,或者说,BFS比较简单一点吧... 这题还有一种解法是状态压缩+BFS...通过开设一个int型变量记录是否拿到宝物,然后暴力..不过这种

HDU ACM 1044 Collect More Jewels BFS+DFS

题意:在一个迷宫中,有一些宝物,从起点走到终点,问在给定的时间内,到达终点后所能拾取珠宝的最大价值. 分析(BFS+DFS): 1.求入口到第一个取宝物的地方的最短距离 2.求第i个取宝物的地方到第i+1个取宝物的地方的最短距离 3.求第n个取宝物的地方到出口的最短距离 4.保证以上3点能在时间L内实现的情况下,取得的宝石价值最大. BFS特点:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元来存储状态) DFS特点:对于解决遍历和求所有问题有效,对于问

1044 [Collect More Jewels] DFS+BFS

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1044 题目大意:在地图中,有M个宝石,每个宝石有不同价值.问在时间限制L之内,从入口到出口这一路上获得的最大价值是多少.拿宝石不额外花时间,走一格用时为1. 关键思想:考虑到BFS和DFS的特点,BFS在解决最短(小)问题是很有效,但内存耗费巨大:DFS可以解决绝大多数搜索问题,但层数较深时,时间开销和栈的开销都很大. 这道题,只用DFS显然是不行的,地图比较大了.但是只用BFS也不行,因为取完之后

50道hdu基础搜索总结(转)

Dfs: 大部分是直接递归枚举,即求满足约束条件下的解,虽不用剪枝,但也需要代码能力. 练习递归枚举的题目: 1241       Oil Deposits (dfs的连通块个数) 1016       Prime Ring Problem 1584       蜘蛛牌(简单dfs,简单的剪枝,还有人用DP做(???)) 1426       Sudoku Killer(练习递归的好题目 or Dancing links(???)) 2510       符号三角形(打表题,写写打表程序还是不错