HDU 1044 Collect More Jewels(BFS+DFS)
http://acm.hdu.edu.cn/showproblem.php?pid=1044
题意:给你一个R*C的棋盘迷宫,要求你在t时间走出迷宫且输出你能获得的最大珠宝价值和.
分析:
首先我们可以知道图中的有效点只有3种:起点,所有宝珠,终点.其中起点我们编号为0,珠宝编号为1到M,终点编号为M+1.
所以我们先用BFS求出以上任意两个有效点之间的距离,然后DFS从起点开始尝试一一走过每一个还没走到的有效点,只要时间不超过t即可.如果当前点是珠宝点,就把该价值加上,如果当前点是终点,就用当前所获得的价值和s更新ans.
不过代码中还有需要剪枝和注意的细节,需要仔细体会代码.
注意:DFS中不可以定序选取下一点,因为最优解可能必须先走B再走A. 很有可能不存在先A,再B,再C等的最优解.
AC代码:
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<ctype.h>
using namespace std;
const int maxn=50+10;
int dr[]={-1,1,0,0};
int dc[]={0,0,-1,1};
int R,C,t,M;
int sum,ans;//sum是所有珠宝价值和,ans是解
char map[maxn][maxn];
int abc[maxn][maxn];//abc[i][j]=x表第i个有效点到第j个有效点之间的距离,如果为0表示不存在路径
int dist[maxn][maxn], vis1[maxn][maxn];//BFS时使用
//注意dist[r][c]表示BFS中的id点到(r,c)的最短距离,其中id为0到M+1.而vis1[r][c]类似
int vis2[maxn]; //DFS时使用
int val[maxn];//宝珠的价值,宝珠从1到M编号
void BFS(int r,int c,int id)
{
queue<int> Q;
vis1[r][c]=1;
dist[r][c]=0;
Q.push(r*C+c); //错误1,这里及后面写成了r*R+c了
while(!Q.empty())
{
int z=Q.front(); Q.pop();
int x=z/C, y=z%C;
for(int d=0;d<4;d++)
{
int xx=x+dr[d], yy=y+dc[d];
if(xx<0||xx>=R||yy<0||yy>=C||map[xx][yy]=='*') continue;
if(vis1[xx][yy]) continue;
vis1[xx][yy]=1;
dist[xx][yy]= dist[x][y]+1;
if(map[xx][yy]=='@') abc[id][0] = dist[xx][yy];
else if(isalpha(map[xx][yy])) abc[id][map[xx][yy]-'A'+1] = dist[xx][yy];
else if(map[xx][yy]=='<') abc[id][M+1]=dist[xx][yy];
Q.push(xx*C+yy);
}
}
}
void dfs(int p,int s,int time)//当前在第p个有效点,拥有价值s的珠宝,花了time时间
{
if(time>t || ans==sum) return; //剪枝,朝时了或已经得到最优解了
if(p==M+1 && s>ans) ans=s; //到达了终点且总价值s>ans,值得更新
else for(int i=1;i<=M+1;i++)
{
if(vis2[i]==1 || abc[p][i]==0) continue; //第i个有效点已经被走过或不存在从p到i的路径
vis2[i]=1;
dfs(i,s+val[i],time+abc[p][i]);
vis2[i]=0;
}
}
int main()
{
int T; scanf("%d",&T);
for(int kase=1;kase<=T;kase++)
{
sum=0;
memset(abc,0,sizeof(abc)); //错误2,忘记了对abs初始化
memset(vis2,0,sizeof(vis2));
scanf("%d%d%d%d",&C,&R,&t,&M);
for(int i=1;i<=M;i++) scanf("%d",&val[i]), sum+=val[i];
val[0]=val[M+1]=0;
for(int i=0;i<R;i++) scanf("%s",map[i]);
for(int i=0;i<R;i++)
for(int j=0;j<C;j++)
{
if(map[i][j]!='@'&&map[i][j]!='<'&&!isalpha(map[i][j])) continue;//非有效点
memset(vis1,0,sizeof(vis1));
memset(dist,0,sizeof(dist));
if(map[i][j]=='@') BFS(i,j,0);
else if(isalpha(map[i][j])) BFS(i,j,map[i][j]-'A'+1);
else if(map[i][j]=='<') BFS(i,j,M+1);
}
vis2[0]=1;
ans=-1;
dfs(0,0,0);//当前在0号点,处于0秒时间且已经获得价值0的珠宝
if(ans>=0) printf("Case %d:\nThe best score is %d.\n",kase,ans);
else printf("Case %d:\nImpossible\n",kase);
if(kase<T) puts("");
}
return 0;
}
分享到:
相关推荐
hdu 1695 GCD(欧拉函数+容斥原理).docx
acm hdu as easy as a+b
【HDU 3993】田忌赛马 题解+勘误 题解这里就略写一下了,主要是勘误。 这道题是2011年之前的多校训练题,2020年的今天,我们一个集训队全部挂在上面了。最后在HDU看到了9年前的讨论区,才知道这题有如下问题: speed...
ACM题库,一些题目和答案,以及解题报告,传上来共享
杭电OnlineJudge 200-2099的解题报告
hdu 3341(ac自动机+状态压缩) 题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A、T、C、G其中...
HDU 1548 --- basic bfs 2. BNU 1440 --- basic dfs 3. POJ 1190 --- dfs + pruning(Strong) 4. UVALive 2243 --- dfs 5. FZU 2196 --- double bfs 6. PKU 1426 --- bfs + pruning 7. BNU 1038 --- dfs transform 8....
hdu 3085 一道bfs题 一点值得注意的,鬼魅先走,mm与gg后走,直接模拟这个这个场景,突出时间的先后性,一秒与一秒的区别。。。这样模拟很难出错
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
搜索 dfs 解题代码 hdu1241
300+ AC 代码 。 大数 , 线段树 , 字符串 , dp.....
Problem Description 话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。 这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。...
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高
八数码的A*算法~不是很高效,但是很适合刚刚学这个算法的朋友们
HDU1059的代码
杭电ACMhdu1163
hdu1001解题报告
hdu 1574 passed sorce
HDU的一题........HDU DP动态规
从简单入门到偏中等的几个题,线段树很灵活,主要懂了lazy操作,其他的自己yy吧。