思路:

先用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[][]={{,},{,-},{,},{-,}};
struct node
{
int x,y;
int times;
int values;
};
bool judge1(int x,int y)//判断能不能走
{
if(x>=&&x<h&&y>=&&y<w&&g[x][y]!=-)
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=;cur.values=;
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=;i<;i++)
{
next.x=cur.x+dir[i][];
next.y=cur.y+dir[i][];
if(judge1(next.x,next.y))
{
next.times=cur.times+;
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]=;
}
}
}
}
}
int main()
{
int i,j,t,cou=;;
char ch;
cin>>t;
while(t--)
{
cou++;
cin>>w>>h>>l>>m;
for(i=;i<m;i++) cin>>M[i];
getchar();
for(i=;i<h;i++)
{
for(j=;j<w;j++)
{
cin>>ch;
switch(ch)
{
case '*':g[i][j]=-;break;
case '.':g[i][j]=;break;
case '@':g[i][j]=;sx=i;sy=j;break;
case '<':g[i][j]=;ex=i;ey=j;break;
default: g[i][j]=M[ch-''-];break;
}
}
}
memset(value,,sizeof(value));
for(i=;i<h;i++)
for(j=;j<w;j++) time[i][j]=;
maxvalue=-;
bfs();
cout<<"Case "<<cou<<":"<<endl;
if(maxvalue>=)
cout<<"The best score is "<<maxvalue<<"."<<endl<<endl;
else cout<<"Impossible"<<endl<<endl;
}
return ;
}

在网上搜了一下别人的代码,大致就是先利用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[][]={{,},{,-},{,},{-,}};
bool judge(int x,int y)//判断该位置是否可走
{
if(x>=&&x<H&&y>=&&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,,sizeof(step));
u=x1*W+y1;
q.push(u);
used[x1][y1]=true;
step[x1][y1]=;
while(!q.empty())
{
u=q.front();
q.pop();
x=u/W;
y=u%W;
for(i=;i<;i++)
{
dx=x+dir[i][];
dy=y+dir[i][];
if(judge(dx,dy))
{
if(!used[dx][dy])
{
used[dx][dy]=true;
step[dx][dy]=step[x][y]+;
if(mp[dx][dy]=='@')
dis[s][]=step[dx][dy];
else if(mp[dx][dy]=='<')
dis[s][M+]=step[dx][dy];
else if(mp[dx][dy]>='A'&&mp[dx][dy]<='J')
dis[s][mp[dx][dy]-'A'+]=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=;i<=M+;i++)
{
if(dis[s][i]==||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=;
cin>>t;
while(t--)
{
sum=;ans=-;
memset(dis,,sizeof(dis));//记得初始化dis
icase++;
cin>>W>>H>>L>>M;
for(i=;i<=M;i++) {cin>>value[i];sum+=value[i];}
for(i=;i<H;i++) cin>>mp[i];
value[]=;value[M+]=;
for(i=;i<H;i++)
{
for(j=;j<W;j++)
{
if(mp[i][j]=='@') bfs(i,j,);
else if(mp[i][j]=='<')bfs(i,j,M+);
else if(mp[i][j]>='A'&&mp[i][j]<='J') bfs(i,j,mp[i][j]-'A'+);
}
}
memset(vis,false,sizeof(vis));
vis[]=true;
dfs(,,);
cout<<"Case "<<icase<<":"<<endl;
if(ans>)
cout<<"The best score is "<<ans<<"."<<endl;
else cout<<"Impossible"<<endl;
if(t) cout<<endl;
}
}

hdu Collect More Jewels的更多相关文章

  1. HDU Collect More Jewels 1044

    BFS + 状态压缩 险过 这个并不是最好的算法 但是写起来比较简单 , 可以AC,但是耗时比较多 下面是代码 就不多说了 #include <cstdio> #include <c ...

  2. HDU 1044 Collect More Jewels(BFS+DFS)

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

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

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

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

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  5. Collect More Jewels(hdu1044)(BFS+DFS)

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  6. hdu 1044 Collect More Jewels

    题意: 一个n*m的迷宫,在t时刻后就会坍塌,问:在逃出来的前提下,能带出来多少价值的宝藏. 其中: ’*‘:代表墙壁: '.':代表道路: '@':代表起始位置: '<':代表出口: 'A'~ ...

  7. hdu 1044(bfs+状压)

    非常经典的一类题型 没有多个出口.这里题目没有说清楚 Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limi ...

  8. HDU 1044 BFS

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  9. hdu 1044(bfs+dfs+剪枝)

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

随机推荐

  1. 2.前端笔记之css

    title: 1.前端笔记之CSS date: 2016-04-05 23:05:51 tags: 前端 categories: w3c --- 作者:刘耀 **出处:http://www.liuya ...

  2. codeforces B. Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/359/B 题目意思:给定n和k的值,需要构造一条长度为2n(每个元素取值范围只能是[1,2n])且元素各不 ...

  3. 10件在PHP 7中不要做的事情

    刚刚在园子里看到一篇特别好的文章,就拿到我的园子里分享了. 1. 不要使用mysql_函数 这一天终于来了,从此你不仅仅“不应该”使用mysql_函数.PHP 7 已经把它们从核心中全部移除了,也就是 ...

  4. ScrollView与TableView实现选择效果

    在cocos2dx中,ScrollView与TableView都可以实现选择效果,其中ScrollView较为原始,TableView的格子大小可以不与winSize一样大. ScrollView实现 ...

  5. 一、HTML和CSS基础--网页布局--如何用css进行网页布局

    什么叫做布局? 又称版式布局,是网页UI设计师将有限的视觉元素进行有机的排列组合. 网页设计的特点 网页可以自适应宽度 网页的高度理论上可以无限延长 网页分栏 分栏又称为分列,常见的布局分为:一列布局 ...

  6. ubuntu下打开终端插件

    一个 nautilus 插件,用于在任意目录中打开终端 nautilus-open-terminal

  7. oracle 10g 学习之创建和管理表(7)

    目标 通过本章学习,您将可以: l  描述主要的数据库对象. l  创建表. l  描述各种数据类型. l  修改表的定义. l  删除,重命名和清空表. 常见的数据库对象 表.视图.序列.索引.同义 ...

  8. C语言字符串比较(转)

    #include <string.h>char s1[10],s2[10]; ... if(strcmp(s1,s2)==0) printf("两字符串相等\n"); ...

  9. 【转】HBase 超详细介绍

    ---恢复内容开始--- http://blog.csdn.net/frankiewang008/article/details/41965543 1-HBase的安装 HBase是什么? HBase ...

  10. 调整linux的时钟

    想把linux时钟调整的正常了. 网上找了找资料,找到了同步办法: http://blog.51yip.com/server/1474.html 即使用: sudo yum install ntp s ...