zoukankan      html  css  js  c++  java
  • HDU 4640 状态压缩DP 未写完

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4640

    解题思路:

    首先用一个简单的2^n*n的dp可以求出一个人访问一个给定状态的最小花费,因为这i个人是等价的,所以用dp[i][mask]表示i个人跑完mask这个状态的最小花费,所以首先枚举集合mask,对于dp[i][mask],枚举mask的子集v,dp[i][mask]可以由dp[1][v],dp[i-1][mask^v]转移过来,注意这里用来合并的集合是不能有重复的,这个类似背包……这样就可以算出对于每个状态三个人访问完的最小花费,之后对于给定的需要访问的状态,枚举包含这个给定状态的集合更新答案就可以了……注意对于刚开始给定的图是不能floyd的,因为要求任意两个人的路径不能相交……还有就是1这个节点可以每个人经过多次,这里需要特殊处理一下……

    以上摘自杭电的解题报告

    下面是我还未写完的代码,我还不会做这个题,所以···还得想想····以后会改好的

      1 #include <cstdio>
      2 #include <queue>
      3 using namespace std;
      4 #define N (1<<17)+5
      5 #define INF 100000000
      6 #define min(a,b) a<b?a:b
      7 #define max(a,b) a>b?a:b
      8 
      9 int n,status; //人数,学妹位置的状态
     10 int d[N][20],dp1[N],dp2[N];
     11 bool in[N][20];
     12 int edge[20][20];
     13 queue<int> qu;
     14 void initScan()
     15 {
     16     int m;
     17     scanf("%d%d",&n,&m);
     18     for(int i=0; i<n; ++i)
     19     {
     20         for(int j=0; j<n; ++j)
     21         {
     22             if(i == j)   edge[i][j] = 0;
     23             else         edge[i][j] = INF;
     24         }
     25     }
     26     while(m--)
     27     {
     28         int u,v,c;
     29         scanf("%d%d%d",&u,&v,&c);
     30         --u,--v;
     31         edge[u][v] = min(edge[u][v],c);
     32         edge[v][u] = edge[u][v];
     33     }
     34     int k;
     35     status = 0;
     36     scanf("%d",&k);
     37     while(k--)
     38     {
     39         int sis;
     40         scanf("%d",&sis);
     41         status |= (1<<(sis-1));
     42     }
     43     status >>= 1;
     44 }
     45 void bfs()
     46 {
     47     memset(in,0,sizeof(in));
     48     memset(d,0x3f,sizeof(d));
     49     qu.push(0);//先城市
     50     qu.push(1);//后状态
     51     d[1][0] = 0;
     52     in[1][0] = true;
     53     while(!qu.empty())
     54     {
     55         int i = qu.front();//状态
     56         qu.pop();
     57         int j = qu.front();//城市
     58         qu.pop();
     59         in[i][j] = false;
     60         for(int k=1; k<n; ++k)
     61         {
     62             int w = i |(1 << k);
     63             if(d[w][k] > d[i][j] + edge[j][k] )
     64             {
     65                 d[w][k] = d[i][j] + edge[j][k];
     66                 if(!d[w][k])
     67                 {
     68                     qu.push(k);
     69                     qu.push(w);
     70                     in[w][k] = 1;
     71                 }
     72             }
     73         }
     74     }
     75 }
     76 void DP1()
     77 {
     78     memset(dp1,0x3f,sizeof(dp1));
     79     for(int i=1; i<(1<<n); ++i)
     80     {
     81         for(int j=0; j<n; ++j)
     82             dp1[i>>1] = min(dp1[i>>1],d[i][j]);
     83     }
     84 }
     85 void DP2()
     86 {
     87     for(int i=1; i<(1<<n); ++i)
     88     {
     89         int  j = i;
     90         while(j)
     91         {
     92             j=(j-1)&i;
     93             dp2[i] = min( dp2[i],max(dp2[j],dp2[i^j]) );
     94         }
     95     }
     96 }
     97 int  solve()
     98 {
     99     int ans = INF;
    100     int j = status;
    101     while(j)
    102     {
    103         j=(j-1)&status;
    104         ans = min( ans,max(dp2[j],dp1[status^j]) );
    105         ans = min(ans,max(dp2[status^j],dp1[j]) );
    106     }
    107     return ans;
    108 }
    109 
    110 int main()
    111 {
    112     freopen("in.cpp","r",stdin);
    113     freopen("myout.cpp","w",stdout);
    114     int t;
    115     scanf("%d",&t);
    116     for(int ser=1; ser<=t; ++ser)
    117     {
    118         initScan();
    119         bfs();
    120         DP1();
    121         for(int i=0; i<(1<<n); ++i)
    122             printf("d[%d] = %d
    ",i,dp1[i]);
    123         DP2();
    124         int ans = solve();
    125         printf("Case %d: ",ser);
    126         if(ans == INF) printf("-1
    ");
    127         else printf("%d
    ",ans);
    128     }
    129     return 0;
    130 }
    View Code

    下面是标程1:

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 #define INF 0x3f3f3f3f
     8 #define N 101
     9 int sta;
    10 int d[N][N];
    11 int dp[1 << 17][17];
    12 bool in[1 << 17][17];
    13 int dp_1[1 << 16], dp_2[1 << 16];
    14 int main() {
    15     int t, cas = 1;
    16     scanf(" %d", &t);
    17     while (t--) {
    18         int n, m;
    19         scanf(" %d %d", &n, &m);
    20 //        if(cas==13) printf("%d %d
    ",n,m);
    21         memset(d, 0x3f, sizeof(d));
    22         for (int i = 0; i < m; i++) {
    23             int x, y, s;
    24             scanf(" %d %d %d", &x, &y, &s);
    25 //            if(cas==13) printf("%d %d %d
    ",x,y,s);
    26             d[x][y] = min(d[x][y], s);
    27             d[y][x] = d[x][y];
    28         }
    29 
    30         queue<int> qu;
    31         qu.push(1);
    32         qu.push(0);
    33         memset(in, 0, sizeof(in));
    34         memset(dp, 0x3f, sizeof(dp));
    35         dp[1][0] = 0;
    36         in[1][0] = true;
    37 
    38         while (!qu.empty()) {
    39             int s_sta = qu.front();
    40             qu.pop();
    41             int s = qu.front() + 1;
    42             qu.pop();
    43             in[s_sta][s - 1] = false;
    44 
    45             for (int i = 0; i < n; i++) {
    46                 int to = i + 1;
    47                 int t_sta = (1 << i) | s_sta;
    48                 if (to == 1)
    49                     continue;
    50                 if (dp[t_sta][to - 1] > dp[s_sta][s - 1] + d[s][to]) {
    51                     dp[t_sta][to - 1] = dp[s_sta][s - 1] + d[s][to];
    52                     if (!in[t_sta][to - 1]) {
    53                         in[t_sta][to - 1] = 1;
    54                         qu.push(t_sta);
    55                         qu.push(to - 1);
    56                     }
    57                 }
    58             }
    59         }
    60 
    61         memset(dp_1, 0x3f, sizeof(dp_1));
    62         for (int i = 1; i < (1 << n); i++) {
    63             for (int j = 0; j < n; j++) {
    64                 dp_1[i >> 1] = min(dp_1[i >> 1], dp[i][j]);
    65             }
    66         }
    67 
    68         int tar = 0, k;
    69         scanf(" %d", &k);
    70 //        if(cas==13) printf("%d
    ",k);
    71         while (k--) {
    72             int x;
    73             scanf(" %d", &x);
    74 //            if(cas==13) printf("%d ",x);
    75             tar |= (1 << (x - 2));
    76         }
    77         int ans = INF;
    78         int tol = (1 << (n - 1)) - 1;
    79         memcpy(dp_2, dp_1, sizeof(dp_1));
    80         for (int i = 1; i < (1 << (n - 1)); i++) {
    81             for (int j = i; j; j = (j - 1) & i) {
    82                 dp_2[i] = min(dp_2[i], max(dp_1[j], dp_1[i ^ j]));
    83             }
    84         }
    85         for (int i = tol; i; i--) {
    86             for (int j = i;; j = (j - 1) & i) {
    87                 if ((i & tar) == tar) {
    88                     ans = min(ans, max(dp_1[j], dp_2[i ^ j]));
    89                 }
    90                 if (j == 0)
    91                     break;
    92             }
    93         }
    94         if (ans == INF)
    95             ans = -1;
    96         printf("Case %d: %d
    ", cas++, ans);
    97     }
    98     return 0;
    99 }
    View Code

    标程2:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<math.h>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<map>
      7 #include<set>
      8 #include<vector>
      9 using namespace std;
     10 typedef __int64 lld;
     11 #define pb push_back
     12 #define mp make_pair
     13 #define X first
     14 #define Y second
     15 #define maxn 20
     16 struct Edge
     17 {
     18     int v,s,next;
     19 }edge[1000010];
     20 int head[maxn];
     21 int pos;
     22 void insert(int x,int y,int s)
     23 {
     24     edge[pos].v=y;
     25     edge[pos].s=s;
     26     edge[pos].next=head[x];
     27     head[x]=pos++;
     28 }
     29 int dis[1<<16][16];
     30 bool vis[1<<16][16];
     31 pair<int,int>queue[2000010];
     32 int rear,front;
     33 int maxQ=2000010;
     34 int dp[1<<16];
     35 int f[1<<16];
     36 int main()
     37 {
     38 //    freopen("input.txt","r",stdin);
     39     int cas;
     40     scanf("%d",&cas);
     41     for(int cc=1;cc<=cas;cc++)
     42     {
     43         int n,m;
     44         scanf("%d %d",&n,&m);
     45         memset(head,0,sizeof(head));
     46         pos=1;
     47         while(m--)
     48         {
     49             int x,y,s;
     50             scanf("%d %d %d",&x,&y,&s);
     51             insert(x,y,s);
     52             insert(y,x,s);
     53         }
     54         memset(dis,-1,sizeof(dis));
     55         memset(vis,false,sizeof(vis));
     56         rear=front=0;
     57         for(int i=head[1];i;i=edge[i].next)
     58         {
     59             int v=edge[i].v;
     60             v-=2;
     61             if(dis[1<<v][v] == -1 || edge[i].s < dis[1<<v][v])
     62             {
     63                 dis[1<<v][v]=edge[i].s;
     64                 if(!vis[1<<v][v])
     65                 {
     66                     vis[1<<v][v]=true;
     67                     queue[front++]=mp(1<<v,v);
     68                 }
     69             }
     70         }
     71         while(rear != front)
     72         {
     73             int mask=queue[rear].X;
     74             int u=queue[rear].Y;
     75             rear++;
     76             if(rear == maxQ)
     77                 rear=0;
     78             vis[mask][u]=false;
     79             for(int i=head[u+2];i;i=edge[i].next)
     80             {
     81                 int v=edge[i].v;
     82                 if(v == 1)
     83                     continue;
     84                 v-=2;
     85                 int next=mask|(1<<v);
     86                 if(dis[next][v] == -1 || dis[mask][u]+edge[i].s < dis[next][v])
     87                 {
     88                     dis[next][v]=dis[mask][u]+edge[i].s;
     89                     if(!vis[next][v])
     90                     {
     91                         vis[next][v]=true;
     92                         queue[front++]=mp(next,v);
     93                         if(front == maxQ)
     94                             front=0;
     95                     }
     96                 }
     97             }
     98         }
     99         memset(dp,-1,sizeof(dp));
    100         dp[0]=0;
    101         int T=1<<(n-1);
    102         for(int mask=1;mask<T;mask++)
    103             for(int i=0;i<n-1;i++)
    104             {
    105                 if(dis[mask][i] == -1)
    106                     continue;
    107                 if(dp[mask] == -1 || dis[mask][i] < dp[mask])
    108                     dp[mask]=dis[mask][i];
    109             }
    110         for(int mask=0;mask<T;mask++)
    111             f[mask]=dp[mask];
    112         for(int k=0;k<2;k++)
    113         {
    114             for(int u=T-1;u>0;u--)
    115                 for(int v1=u;;v1=(v1-1)&u)
    116                 {
    117                     int v2=u^v1;
    118                     if(dp[v1] == -1 || f[v2] == -1)
    119                     {
    120                         if(v1 == 0)
    121                             break;
    122                         continue;
    123                     }
    124                     if(dp[u] == -1 || max(dp[v1],f[v2]) < dp[u])
    125                         dp[u]=max(dp[v1],f[v2]);
    126                     if(v1 == 0)
    127                         break;
    128                 }
    129         }
    130         int Q;
    131         scanf("%d",&Q);
    132         int mask=0;
    133         while(Q--)
    134         {
    135             int x;
    136             scanf("%d",&x);
    137             x-=2;
    138             mask|=1<<x;
    139         }
    140         int ans=-1;
    141         for(int u=0;u<T;u++)
    142             if((u&mask) == mask)
    143             {
    144                 if(dp[u] == -1)
    145                     continue;
    146                 if(ans == -1 || dp[u] < ans)
    147                     ans=dp[u];
    148             }
    149         printf("Case %d: %d
    ",cc,ans);
    150     }
    151     return 0;
    152 }
    View Code
  • 相关阅读:
    代码重构编译---make
    clickhouse日期函数
    连续登陆天数+最大登陆天数
    clickhouse基本使用
    数组
    CK优化
    Hive查询优化~布隆过滤器使用
    Presto常见问题优化
    Presto原理解析
    几种排序说明
  • 原文地址:https://www.cnblogs.com/allh123/p/3235342.html
Copyright © 2011-2022 走看看