hdu3681(二分+状态压缩dp+bfs)
2016-07-09 13:47
323 查看
链接:点击打开链接
题意:在一个n*m的矩阵中,‘F’为起点,‘G’是加油站,遇到加油站油箱直接加满,'Y'是开关,‘F’是空地,‘D’是障碍,每走一步消耗一单位油,问油箱最小是多少可以将所有开关都走到
代码:
题意:在一个n*m的矩阵中,‘F’为起点,‘G’是加油站,遇到加油站油箱直接加满,'Y'是开关,‘F’是空地,‘D’是障碍,每走一步消耗一单位油,问油箱最小是多少可以将所有开关都走到
代码:
#include <iostream> #include <stdio.h> #include <cstring> #include <algorithm> #include <queue> using namespace std; int n,m,num,new_S,start; char str[55][55]; int xx[]={1,0,-1,0}; int yy[]={0,-1,0,1}; int dp[1<<16][20]; int dis[20][20][20][20]; struct node{ int x,y; }s[15*15]; void bfs(node st){ queue<node>que; node cur,temp; int i; que.push(st); dis[st.x][st.y][st.x][st.y]=0; while(que.size()){ cur=que.front(); que.pop(); for(i=0;i<4;i++){ temp.x=cur.x+xx[i]; temp.y=cur.y+yy[i]; if(temp.x>=0&&temp.x<n&&temp.y>=0&&temp.y<m) if(str[temp.x][temp.y]!='D'){ if(dis[st.x][st.y][temp.x][temp.y]==-1){ dis[st.x][st.y][temp.x][temp.y]=dis[st.x][st.y][cur.x][cur.y]+1; que.push(temp); } } } } } //bfs求起点,加油站,开关到所有点的距离 int judge(int mid){ int i,j,k,ans; ans=-1; memset(dp,-1,sizeof(dp)); dp[1<<start][start]=mid; //dp[i][j]为状态是i时结尾是j时油箱的剩余 for(i=0;i<(1<<num);i++){ //旅行商问题,只不过每次要判断状态是否是最终状态 for(j=0;j<num;j++){ if(((i&(1<<j))==0)||dp[i][j]==-1) continue; if((i&new_S)==new_S) ans=max(ans,dp[i][j]); for(k=0;k<num;k++){ if(j==k||(i&(1<<k))||dis[s[j].x][s[j].y][s[k].x][s[k].y]==-1) continue; if(dp[i][j]-dis[s[j].x][s[j].y][s[k].x][s[k].y]<0) continue; dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]-dis[s[j].x][s[j].y][s[k].x][s[k].y]); if(str[s[k].x][s[k].y]=='G') //遇到加油站重置油箱 dp[i|(1<<k)][k]=mid; } } } if(ans>=0) return 1; return 0; } int main(){ int i,j,k,l,r,ans,mid; while(scanf("%d%d",&n,&m)!=EOF&&(m||n)){ num=new_S=0; memset(dis,-1,sizeof(dis)); for(i=0;i<n;i++) for(j=0;j<m;j++){ cin>>str[i][j]; if(str[i][j]=='F'){ start=num; s[num].x=i,s[num].y=j; new_S|=(1<<num); num++; } else if(str[i][j]=='G'){ s[num].x=i,s[num].y=j; num++; } else if(str[i][j]=='Y'){ s[num].x=i,s[num].y=j; new_S|=(1<<num); num++; } //将所有Y和F的状态进行压缩,相当于 } //求tsp for(i=0;i<num;i++) bfs(s[i]); l=0,r=300,ans=-1; while(l<=r){ //二分油箱的大小 mid=(l+r)>>1; if(judge(mid)){ ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- Linux下tesseract-ocr安装
- python连接两个字符串的另外两种高效率的方法
- Android搭建项目框架
- vs2010配置OpenCV2.4.7详细步骤
- Redis Cluster分区实现原理
- Runtime实战之定制TabBarItem大小(京东tabar实现机制)
- 队列、栈
- poj 2184 01背包应用
- HTML5之客户端存储数据
- webgl入门之一:概述
- iic模块PCF8574驱动1602学习记载
- PL/SQL实现JAVA中的split()方法的小例子
- 设计模式-单例模式
- css3-3D透明照片墙
- 欢迎使用Markdown编辑器写博客
- php示例代码之empty函数
- centos搭建mysql主从复制,读写分离
- 消息中间件activemq-5.13.0整合spring
- php示例代码之读取文件
- LAMP配置虚拟目录