hdu 4114 状态压缩+最短路

来源:互联网 发布:win7旗舰版自带sql吗 编辑:程序博客网 时间:2024/05/18 15:52

http://acm.hdu.edu.cn/showproblem.php?pid=4114

人渣不拆啊,写了个spfa,T了,然后写了个dij,MLE了。我呵呵呵,然后我以为难道不是最短路???就看了下题解。。。发现是自己SB了。。。我真弱啊,真弱。。。。


对于这道题:很容易想到用状态压缩来表示某个状态下的最短路,


dis[50][1<<8][1<<8],dis[N][V][T]表示到N号节点,浏览过的点的状态为V,拿着的票的状态为T,时候的最短路程。

然后就是个最短路了,思路很简单。

但是需要注意的是:当游览过某个景点之后,就认为拿着了这个景点的票了!!!这个优化很重要。。。要不就是SPFA,TLE。。dij由于边太多MLE。。。我还Dij写SB了。。。真是太弱了


#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int maxn = 51;const int INF = 0x3ffffff;int n,m,k;int pass[maxn];int place[maxn];int len[maxn][maxn];int play[maxn][2];int dis[maxn][1<<8][1<<8];bool vis[maxn][1<<8][1<<8];struct E{int s,w;void get(int &u,int &vi,int &ti,int &w){u=s/(1<<16);vi=s/(1<<8)%(1<<8);ti=s%(1<<8);w=this->w;}void set(int s,int w){this->s=s;this->w=w;}friend bool operator < (const E &a,const E &b){return a.w>b.w;}};int get_hash(int u,int vi,int ti){return u*(1<<16)+vi*(1<<8)+ti;}priority_queue<E>q;void dij(){for(int i=1;i<=n;i++){for(int b1=0;b1<1<<k;b1++){for(int b2=0;b2<1<<k;b2++){dis[i][b1][b2]=INF;vis[i][b1][b2]=false;}}}while(!q.empty())q.pop();E tmp;tmp.set(get_hash(1,0,0),0);q.push(tmp);int u,vi,ti,w;while(!q.empty()){tmp=q.top();q.pop();tmp.get(u,vi,ti,w);if(vis[u][vi][ti])continue;dis[u][vi][ti]=w;vis[u][vi][ti]=true;if(u==1&&vi==(1<<k)-1&&ti==vi)return;int d=0;if((vi|place[u])!=vi&&!vis[u][vi|place[u]][ti]){for(int i=0;i<k;i++){if( (place[u]&(1<<i)) && !(vi&(1<<i)) ){if(ti & (1<<i) ){d+=play[i][1];}else d+=play[i][0];}}if( w+d<dis[u][vi|place[u]][ti]){dis[u][vi|place[u]][ti]=w+d;tmp.set(get_hash(u,vi|place[u],ti),w+d);q.push(tmp);}}if((ti|pass[u]|vi)!=ti){if(!vis[u][vi][ti|pass[u]|vi] && w<dis[u][vi][ti|pass[u]|vi]){dis[u][vi][ti|pass[u]|vi]=w;tmp.set(get_hash(u,vi,ti|pass[u]|vi),w);q.push(tmp);}}for(int i=1;i<=n;i++){if(!vis[i][vi][ti|vi] && w+len[u][i] < dis[i][vi][ti|vi]){dis[i][vi][ti|vi]=w+len[u][i];tmp.set(get_hash(i,vi,ti|vi),w+len[u][i]);q.push(tmp);}}}}int main(){int T,ca=1;scanf("%d",&T);while(T--){printf("Case #%d: ",ca++);scanf("%d%d%d",&n,&m,&k);memset(pass,0,sizeof(pass));memset(place,0,sizeof(place));for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){len[i][j]=i==j?0:INF;}}for(int i=0;i<m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);len[u][v]=len[v][u]=min(len[u][v],w);}for(int i=0;i<k;i++){int p;scanf("%d%d%d",&p,&play[i][0],&play[i][1]);place[p]=place[p]|(1<<i);int nt;scanf("%d",&nt);for(int j=0;j<nt;j++){scanf("%d",&p);pass[p]|=1<<i;}}dij();printf("%d\n",dis[1][(1<<k)-1][(1<<k)-1]);}}





原创粉丝点击