• hdu 4114 Disney's FastPass 状压dp


    点击打开链接


    题意:

    游戏园里有N个区域,有M条边连接这N个区域,有K个要访问的景点。对于每个景点告诉你这个景点所在的区域,要访问这个景点需要等待一定时间,如果没有FastPass,等待时间有Ti,否则等待时间为FTi,接下来的Ni,表示有Ni个区域可以得到这个景点的FastPass,问从区域1出发,再回到区域1所需要的最少时间。


    思路:

    状态压缩,dis[i][s1][s2],表示当前走到这个点,s1表示拿到了哪些景点的FastPass,s2表示已经访问了哪几个景点。

    但是需要注意的是:当游览过某个景点之后,就认为拿着了这个景点的票了!!!这个优化很重要

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n,m,k;
     5 int dis[55][55],dp[55][1<<8][1<<8],pos[10],t[10],ft[10],pas[55];
     6 int ans;
     7 
     8 void init(){
     9     ans = 0x3f3f3f3f;
    10     memset(dp,0x3f,sizeof(dp));
    11     memset(dis,0x3f,sizeof(dis));
    12     memset(pas,0,sizeof(pas));
    13 }
    14 
    15 void floyd(){
    16     for(int k=1; k<=n; k++)
    17         for(int i=1; i<=n; i++)
    18             for(int j=1; j<=n; j++)
    19                 dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
    20 }
    21 
    22 void solve(){
    23     dp[1][0][0] = 0;
    24     for(int s1=0; s1<(1<<k); s1++){
    25         for(int s2=0; s2<(1<<k); s2++){
    26             for(int i=1; i<=n; i++){
    27                 int now = dp[i][s1][s2];
    28                 if(now==0x3f3f3f3f) continue;
    29                 if(s2==(1<<k)-1) ans = min(ans,now+dis[i][1]);
    30                 for(int j=0; j<k; j++){
    31                     if((s2&(1<<j)) == 0){ // 没走过第j个景点
    32                         int& nxt = dp[pos[j]][s1|pas[pos[j]]][s2^(1<<j)]; // 当游览过某个景点之后,就认为拿着了这个景点的票了!!!
    33                         int add = dis[i][pos[j]];
    34                         if(s1 & (1<<j)) add += ft[j];
    35                         else add += t[j];
    36                         nxt = min(nxt,now+add);
    37                     }
    38                 }
    39                 for(int j=1; j<=n; j++){  // 中转 通过j得到fastpass
    40                     int& nxt = dp[j][s1|pas[j]][s2];
    41                     int add = dis[i][j];
    42                     nxt = min(nxt,now+add);
    43                 }
    44             }
    45         }
    46     }
    47 }
    48 
    49 int main(){
    50     int T; cin>>T;
    51     for(int cas=1; cas<=T; cas++){
    52         
    53         init();
    54         cin >> n >> m >> k;
    55         for(int i=1; i<=m; i++){
    56             int u,v,w; cin>>u>>v>>w;
    57             dis[u][v] = w; dis[v][u] = w;
    58         }
    59         for(int i=0;i<n;i++) dis[i][i]=0; 
    60         floyd();
    61 
    62         for(int i=0; i<k; i++){
    63             cin >> pos[i] >> t[i] >> ft[i];
    64             int num; cin>>num;
    65             for(int j=0; j<num; j++){
    66                 int tmp; cin>>tmp;
    67                 pas[tmp] |= (1<<i);
    68             }
    69         }
    70 
    71         solve();
    72 
    73         cout << "Case #" << cas << ": " << ans << endl;
    74 
    75     }
    76 }
  • 相关阅读:
    JDK下载 安装 配置
    C#中的委托与事件 笔记
    转载 -- C# 中的委托和事件
    Laravel5 路由问题 /home页面无法访问
    eclipse的android智能提示设置
    svn在linux下的使用(ubuntu命令行模式操作svn)
    gdb结合coredump定位崩溃进程
    Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
    struct的初始化,拷贝及指针成员的使用技巧
    C++ 资源大全
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827730.html
Copyright © 2020-2023  润新知