zoukankan      html  css  js  c++  java
  • LightOJ1316 A Wedding Party(状压DP)

    这题事实上只需要关心15个商店和一个起点一个终点,预处理出这几个点之间的最短距离。Floyd会超时,用Dijkstra即可。

    然后就是dp[u][S]表示已经经过商店集合S且当前在第u个商店所花的最少时间。

    最后的结果是找到所有dp[u][S]有解且u能到达终点的最大的|S|,而最短时间就是dp[u][S]+dist[u][vt]。

    细节还挺多的。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define INF (1<<29)
     6 
     7 int d[15][1<<15];
     8 int G[555][555],dist[555][555],shop[15];
     9 void dijkstra(int vs,int n){
    10     for(int i=0; i<n; ++i) dist[vs][i]=INF;
    11     dist[vs][vs]=0;
    12     bool vis[555]={0};
    13     for(int i=0; i<n; ++i){
    14         int u=-1,mm=INF;
    15         for(int v=0; v<n; ++v){
    16             if(!vis[v] && mm>dist[vs][v]){
    17                 mm=dist[vs][v];
    18                 u=v;
    19             }
    20         }
    21         if(u==-1) break;
    22         vis[u]=1;
    23         for(int v=0; v<n; ++v){
    24             if(!vis[v] && G[u][v]!=INF && dist[vs][v]>dist[vs][u]+G[u][v]){
    25                 dist[vs][v]=dist[vs][u]+G[u][v];
    26             }
    27         }
    28     }
    29 }
    30 int getCnt(int s){
    31     int res=0;
    32     for(int i=0; i<15; ++i){
    33         if((s>>i)&1) ++res;
    34     }
    35     return res;
    36 }
    37 int cnt[1<<15];
    38 int main(){
    39     for(int i=0; i<(1<<15); ++i) cnt[i]=getCnt(i);
    40     int t,n,m,s,a,b,c;
    41     scanf("%d",&t);
    42     for(int cse=1; cse<=t; ++cse){
    43         scanf("%d%d%d",&n,&m,&s);
    44         for(int i=0; i<n; ++i){
    45             for(int j=0; j<n; ++j) G[i][j]=INF;
    46         }
    47         for(int i=0; i<s; ++i) scanf("%d",&shop[i]);
    48         while(m--){
    49             scanf("%d%d%d",&a,&b,&c);
    50             G[a][b]=min(G[a][b],c);
    51         }
    52         dijkstra(0,n);
    53         for(int i=0; i<s; ++i) dijkstra(shop[i],n);
    54 
    55         if(dist[0][n-1]==INF){
    56             printf("Case %d: Impossible
    ",cse);
    57             continue;
    58         }
    59 
    60         for(int i=0; i<s; ++i){
    61             for(int j=0; j<(1<<s); ++j) d[i][j]=INF;
    62         }
    63         for(int i=0; i<s; ++i){
    64             d[i][1<<i]=dist[0][shop[i]];
    65         }
    66         for(int i=1; i<(1<<s); ++i){
    67             for(int j=0; j<s; ++j){
    68                 if(((i>>j)&1)==0) continue;
    69                 for(int k=0; k<s; ++k){
    70                     if(k==j || ((i>>k)&1)==0) continue;
    71                     d[j][i]=min(d[j][i],d[k][i^(1<<j)]+dist[shop[k]][shop[j]]);
    72                 }
    73             }
    74         }
    75         int mx=0,mm=INF;
    76         for(int i=1; i<(1<<s); ++i){
    77             for(int j=0; j<s; ++j){
    78                 if(d[j][i]==INF || dist[shop[j]][n-1]==INF) continue;
    79                 mx=max(mx,cnt[i]);
    80             }
    81         }
    82         for(int i=1; i<(1<<s); ++i){
    83             for(int j=0; j<s; ++j){
    84                 if(d[j][i]==INF) continue;
    85                 if(cnt[i]==mx) mm=min(mm,d[j][i]+dist[shop[j]][n-1]);
    86             }
    87         }
    88         if(mm!=INF) printf("Case %d: %d %d
    ",cse,mx,mm);
    89         else printf("Case %d: 0 %d
    ",cse,dist[0][n-1]);
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    RESTful API 设计指南
    理解RESTful架构
    django-mysqlclient_1193错误
    获取当前脚本所在的目录和路径
    20191007
    20191005
    20191001
    20190927
    20190922
    莫比乌斯反演证明
  • 原文地址:https://www.cnblogs.com/WABoss/p/5156600.html
Copyright © 2011-2022 走看看