【3阶动规+状态压缩】s到达G
来源:互联网 发布:海泰克触摸屏编程手册 编辑:程序博客网 时间:2024/09/21 09:02
S对应point[0],G对应Point[n-1].中间点对应1~n-2
针对每个中间state有
len[state][s]+dist[s][t] >= len[state|(1<<(t-1))][t],state=1 to 1<<(n-2)-1
其中len[state][s]<无穷(点s可以且已经被state最后访问),dist[s][t]<无穷(点s可以到达t),且state&(1<<(t-1))==0 (即点t尚未被状态state访问,从而state可达t)
#include <stdio.h>#include <assert.h>#include <string.h>#include <vector>#include <queue>#include <iostream>using namespace std;typedef pair<int,int> Pair;#define INF 0x7ffffff#define MAXSIZE 10000class Orienteering{ public: void main(); private: bool init(char buf[],int &w,int &h,vector<Pair> &points); void bfs(char buf[],int w,int h,const vector<Pair> &points,vector<vector<int> > &dist); int dp(const vector<vector<int> > &dist);}; /** * calculate min-cost of all (i,j), point i and j in points[] * and store in dist[i][j] * params: @buf[]: the map * @w: the width @h: the height, 0<w,h<=100 * @points[]: the point array, * @dist[][]: elements init as INF * output: @dist[][] */void Orienteering::bfs(char buf[],int w,int h,const vector<Pair> &points,vector<vector<int> > &dist){ int n=points.size(); // record points' number on pNum[][] int *pNum=new int[w*h]; memset(pNum,-1,w*h*sizeof(int)); for(int i=0;i<n;i++){ const Pair &p=points[i]; pNum[p.first*w+p.second]=i; } // minDst[i][j] is the min-distance between point (i,j) int * minDst=new int[w*h]; // four directions int drt[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; // find nearest distances from point[i] to other points for(int i=0;i<n;i++){ const Pair &p=points[i]; queue<Pair> que; que.push(p); int cnt=1; memset(minDst,-1,w*h*sizeof(int)); minDst[p.first*w+p.second]=0; while(!que.empty()){ Pair p=que.front(); que.pop(); int x0=p.first,y0=p.second; // visit direction: left/right/up/down for(int j=0;j<4;j++){ int x=x0+drt[j][0],y=y0+drt[j][1]; // ignore positions which is visited or can't be visited if(x<0 || y<0 || x>=h || y>=w || buf[x*w+y]=='#'|| minDst[x*w+y]>=0) continue; minDst[x*w+y]=minDst[x0*w+y0]+1; que.push(Pair(x,y)); int k=pNum[x*w+y]; if(k>=0){// if readched a point dist[i][k]=minDst[x*w+y]; // if(k<i) assert(dist[k][i]==dist[i][k]); cnt++; if(cnt==n) break; } } } } delete[] minDst; delete[] pNum;}/** * find the min-cost from point 0 to point n-1 with all other points visited * params: @dist[i][j]: min-distance from point i to j * return: the min-distance from point 0 to n-1 with all check-points passed * INF if not reachable or input don't satisfy specifications */int Orienteering::dp(const vector<vector<int> > &dist){ int n=dist.size(); int lp=0,rp=n-1; if(n<2||n>sizeof(int)*8) return INF; int size=1<<(n-2), lst=size-1;// lst is the state that all check-points(1~n-2) has been visited // len[i][s] stands for current visit state is i(compressed binary number for check-points 1~n-2), with point s last visited vector<vector<int> > len(size,vector<int>(n-1,INF)); vector<vector<int> > path(size,vector<int>(n-1,INF)); len[0][lp]=0;// init: in state 0, with point 0(start-point 'S') last visited for(int i=0;i<=lst;i++){ for(int s=lp;s<rp;s++){ if(len[i][s]<INF){ for(int t=lp+1,mask=1;t<rp;t++,mask<<=1){ if(!(i&mask) && dist[s][t]<INF){// try to go from <state i,point s> to <state i|mask,point t> int tmp=len[i|mask][t]; len[i|mask][t]=min(len[i|mask][t],len[i][s]+dist[s][t]); if(len[i|mask][t] < tmp) path[i|mask][t]=s;// record the path } } } } } // go to end-point rp from <state lst, point s> int minLen=INF; int l=INF; for(int s=lp;s<rp;s++) if(len[lst][s]<INF && dist[s][rp]<INF){ int tmp=minLen; minLen=std::min(minLen,len[lst][s]+dist[s][rp]); if(minLen<tmp){ l=s; } } // print min-path int state=lst,point=l; cout<<"print path:"<<endl; cout<<rp<<" <- "; while(point<INF){ cout<<point; if(point==0) break; cout<<" <- "; int tmp=path[state][point]; state-=(1<<(point-1)); point=tmp; } cout<<endl; return minLen; }/** * init the points and buffer * record map in buf[], check points and S/G in points[] * @points[]: points[0] as point 'S', 1~n-2 as check-points, n-1 as 'G' * @return: true if parameters satisfy conditions */bool Orienteering::init(char buf[],int &w,int &h,vector<Pair> &points){ scanf("%d %d\n",&w,&h); // if w or h don't satisfy conditions if( w<1 || h<1 || w*h>MAXSIZE ) return false; Pair tmp(-1,-1),start=tmp,end=tmp; points.clear(); points.push_back(start); for(int i=0;i<h;i++){ scanf("%s\n",buf+i*w); for(int j=0;j<w;j++){ char c=buf[i*w+j]; if(c=='@') points.push_back(Pair(i,j)); else if(c=='S') { if(start!=tmp) return -1; // S duplicated start=Pair(i,j); } else if(c=='G') { if(end!=tmp) return -1; // G duplicated end=Pair(i,j); } } } // if no 'S' or 'G' found if(start==tmp||end==tmp) return false; points[0]=start; points.push_back(end); if(points.size()>20) return false; return true;}/** * */void Orienteering::main(){ // record points that must be passed int w,h; char buf[10010]; vector<Pair> points; if(!Orienteering::init(buf,w,h,points)) { printf("-1\n"); return; }; // find the nearest distance between points in points[] int n=points.size(); vector<vector<int> > dist(n,vector<int>(n,INF)); Orienteering::bfs(buf,w,h,points,dist); // find the nearest path from start-point to end-point passing all points int dst=Orienteering::dp(dist); if(dst==INF) printf("-1\n"); else printf("%d\n",dst);}int main(int argc,char *argv[]){ Orienteering o; o.main(); return 0;}
0 0
- 【3阶动规+状态压缩】s到达G
- POJ 2411 Mondriaan's Dream 状态压缩
- POJ 2411 Mondriaan's Dream(状态压缩)
- poj2411 Mondriaan's Dream 状态压缩dp
- hdu 1400 Mondriaan's Dream 状态压缩
- POJ2411:Mondriaan's Dream(状态压缩)
- poj2411 Mondriaan's Dream 状态压缩dp
- 10817 - Headmaster's Headache(状态压缩)
- UVA - 10817 Headmaster's Headache 状态压缩
- poj2411Mondriaan's Dream(状态压缩dp)
- hdu_4352_XHXJ's LIS(数位DP+状态压缩)
- 【poj2411】Mondriaan's Dream 状态压缩dp
- POJ_2411_Mondriaan's Dream【状态压缩DP】
- POJ 2411 Mondriaan's Dream 状态压缩
- pku 2411 Mondriaan's Dream(状态压缩DP)
- pku 2411 Mondriaan's Dream dp 状态压缩
- dp专辑F - Mondriaan's Dream [状态压缩]
- JOJ 2190: Mondriaan's Dream (状态压缩DP +DFS)
- poj 1186:方程的解数
- 3. String/集合类/IO流学习
- Linux终端实现根据应用包名过滤Logcat
- android不将apk包编译到系统里的方法
- Flask request,g,session的实现原理
- 【3阶动规+状态压缩】s到达G
- YII 邮件发送 phpmailer发送邮件!Yii自定义类引用
- B 树、B+ 树、B* 树
- 杂谈:adobe 要离开了?
- FOJ1007
- 12个鸡蛋的故事
- 常用黑盒测试设计用例方法一 等价类划分
- 作业
- (翻译)C++ 多态机制