BOJ 4228 哈哈哈
来源:互联网 发布:鲲鹏网络传媒有限公司 编辑:程序博客网 时间:2024/06/05 11:25
题目链接~~>
做题感悟:这题一看就知道要用状态压缩,本题和HDU 1429 胜利大逃亡(续)差不多。
解题思路:你可以把宝物压缩为二进制,例如:01001 代表你已经拿过 1 号和 4 号宝物了 0 代表相应的宝物没拿。用同样的方法把拿某个物品的前提条件也映射成二进制。假如你现在遇到 3 号宝物,如果3号宝物的前提条件是拿到 1 号 和 4 号宝物才能拿 3 号,那么前提条件可以用二进制表示为 :01001 那么只要将这个二进制与你当前的 key 相与如果结果还是等于前提条件的二进制,表示前提条件已经满足。so 3 号物品可以取走(前提是没取过三号物品),否则不可以。
代码:
#include<stdio.h>#include<iostream>#include<map>#include<stack>#include<string>#include<string.h>#include<stdlib.h>#include<math.h>#include<vector>#include<queue>#include<algorithm>using namespace std ;#define LEN sizeof(struct node)#define lld long long intconst double PI = 3.1415926 ;const double INF = 99999999 ;const int MX =25 ;int n,m,mx ;char s[MX][MX] ;int b[MX] ;int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1} ;bool vis[MX][MX][MX] ;// 标记数组struct node{ int x,y,key,step ;} ;bool search(int x,int y) // 判断是否出界{ if(x<0||y<0||x>=n||y>=m||s[x][y]=='#') return false ; return true ;}int bfs(int x,int y){ int key,sx,sy,temp ; memset(vis,false,sizeof(vis)) ; queue<node>q ; node curt,next ; curt.x=x ; curt.y=y ; curt.key=0 ; curt.step=0 ; vis[x][y][0]=true ; q.push(curt) ; while(!q.empty()) { curt=q.front() ; q.pop() ; if(curt.key==(1<<mx)-1&&s[curt.x][curt.y]=='E') return curt.step ; for(int i=0 ;i<4 ;i++) { next.x=sx=curt.x+dx[i] ; next.y=sy=curt.y+dy[i] ; next.step=curt.step+1 ; next.key=key=curt.key ; if(search(sx,sy)) // 判断是否出界 { if(s[sx][sy]>='0'&&s[sx][sy]<='9') // 是宝藏 { temp=s[sx][sy]-'0' ; if(key&(1<<temp)) // 已经取过 { if(!vis[sx][sy][key]) { vis[sx][sy][key]=true ; next.key=key ; q.push(next) ; } } else // 还没取过 { temp=s[sx][sy]-'0' ; if((key&b[temp])==b[temp])// 取该宝物的前提条件已经满足 { next.key=key|(1<<temp) ; vis[sx][sy][next.key]=true ; q.push(next) ; } else if(!vis[sx][sy][key])// 前提条件没满足 { vis[sx][sy][key]=true ; next.key=key ; q.push(next) ; } } } else if(!vis[sx][sy][key])// 不是宝藏 { next.key=key ; vis[sx][sy][key]=true ; q.push(next) ; } } } } return -1 ;}int main(){ int sx,sy ; while(~scanf("%d%d",&n,&m)) { for(int i=0 ;i<n ;i++) { scanf("%s",s[i]) ; for(int j=0 ;j<m ;j++) if(s[i][j]=='S') { sx=i ; sy=j ; } else if(s[i][j]>='0'&&s[i][j]<='9') mx++ ; } int nx,ans=0,y ; for(int i=0 ;i<mx ;i++) { scanf("%d",&nx) ; ans=0 ; for(int j=0 ;j<nx ;j++) { scanf("%d",&y) ; ans=ans|(1<<y) ; } b[i]=ans ;// 取第 i 个宝物的前提条件 } int an=bfs(sx,sy) ; if(an!=-1) printf("%d\n",an) ; else printf("Impossible\n") ; } return 0 ;}
0 0
- BOJ 4228 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 哈哈哈
- 火星人敏捷开发博客APP上线了
- C++ 面试题(一) this指针
- 建造者模式
- switch中case语句的可用类型
- SQ3R学习法(Survy, Question, Read, Recite, Review)
- BOJ 4228 哈哈哈
- 1 数据结构基础概念
- Lake Counting
- 微信公众平台开发C#实现
- Introduction to SSE Programming
- c++设计模式之观察者模式
- 疯狂 dp(一) 线性 dp
- 获得PHP环境系统信息
- 采用邻接表存储结构,编写一个判别无向图中任意给定的两个顶点之间是否存在一条长度为k的简单路径的算法。