• bzoj 2595 斯坦纳树


     题目大意:

    选定一些格子保证景点对应的格子通过这些格子连通,保证选定的所有格子对应的权值和最小

    这是相当于理解为将所有点形成的最小生成树

    这里点的个数很少,所以可以对每一个点进行状态压缩

    f[st][i]表示连通性至少为st,且经过i点的最小距离

    方程1.f[st][i] = Min{f[s][i] + f[st - s][i]}(s为st的子集)

    方程2.f[st][i] = Min{f[st][j] + w(i,j)}(i,j之间有边相连)

    那么可以看出来大的状态总是跟小的状态有关,那么总是先求出小的状态集合

    利用spfa求解所有状态对应的点跑最短路对其他格点进行松弛

    我到现在也不知道为什么这样写效率会高

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <queue>
      5 using namespace std;
      6 typedef pair<int,int> pii;
      7 #define N 11
      8 const int MAXN=1<<N;
      9 const int INF = 0x3f3f3f3f;
     10 int n , m ;
     11 
     12 struct Node{
     13     int x , y , s;
     14     Node(){}
     15     Node(int x , int y , int s):x(x),y(y),s(s){}
     16 };
     17 Node pre[N][N][MAXN];//用于回溯找上一个节点
     18 
     19 int w[N][N] , dp[N][N][MAXN] , dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
     20 bool vis[N][N] , flag[N][N];
     21 queue<pii> que;
     22 
     23 bool ok(int x , int y){return x>=1&&x<=n&&y>=1&&y<=m;}
     24 
     25 void spfa(int state)
     26 {
     27     while(!que.empty()){
     28         pii u = que.front();
     29         que.pop();
     30         int x = u.first , y = u.second;
     31         vis[x][y] = false;
     32         for(int i=0 ; i<4 ; i++){
     33             int xx = x+dir[i][0] , yy = y+dir[i][1];
     34             if(!ok(xx,yy)) continue;
     35             if(dp[xx][yy][state]>dp[x][y][state]+w[xx][yy]){
     36                 dp[xx][yy][state]=dp[x][y][state]+w[xx][yy];
     37                 pre[xx][yy][state] = Node(x , y , state);
     38                 if(!vis[xx][yy]) que.push(make_pair(xx , yy));
     39             }
     40         }
     41     }
     42 }
     43 
     44 void huisu(int x , int y , int s)
     45 {
     46     flag[x][y] = true;
     47     if(pre[x][y][s].s == 0) return;
     48     huisu(pre[x][y][s].x , pre[x][y][s].y , pre[x][y][s].s);
     49     if(pre[x][y][s].x==x && pre[x][y][s].y==y) huisu(pre[x][y][s].x , pre[x][y][s].y , s-pre[x][y][s].s);
     50 }
     51 
     52 void print()
     53 {
     54     for(int i=1 ; i<=n ; i++){
     55         for(int j=1 ; j<=m ; j++)
     56             if(!w[i][j]) printf("x");
     57             else if(flag[i][j]) printf("o");
     58             else printf("_");
     59         puts("");
     60     }
     61 }
     62 
     63 int main()
     64 {
     65    // freopen("in.txt" , "r" , stdin);
     66     while(~scanf("%d%d" , &n , &m))
     67     {
     68         int num = 0;
     69         memset(dp , 0x3f , sizeof(dp));
     70         memset(pre , 0 , sizeof(pre));
     71         for(int i=1 ; i<=n ; i++){
     72             for(int j=1 ; j<=m ; j++){
     73                 scanf("%d" , &w[i][j]);
     74                 if(!w[i][j]){
     75                     dp[i][j][1<<num] = 0;
     76                     num++;
     77                 }
     78             }
     79         }
     80         int ALL_STATE = 1<<num;
     81         for(int k=1 ; k<ALL_STATE ; k++){
     82             for(int i=1 ; i<=n ; i++){
     83                 for(int j=1 ; j<=m ; j++){
     84                     for(int s=(k-1)&k ; s ; s=(s-1)&k){
     85                         int tmps = k-s;
     86                         if(dp[i][j][k]>dp[i][j][s]+dp[i][j][tmps]-w[i][j]){
     87                             dp[i][j][k] = dp[i][j][s]+dp[i][j][tmps]-w[i][j];
     88                             pre[i][j][k] = Node(i , j , s);
     89                         }
     90                     }
     91                     if(dp[i][j][k]<INF) que.push(make_pair(i , j)) , vis[i][j]=true;
     92                 }
     93             }
     94             spfa(k);
     95         }
     96         memset(flag , 0 , sizeof(flag));
     97         for(int i=1 ; i<=n ; i++)
     98             for(int j=1 ; j<=m ; j++){
     99                 if(!w[i][j]){
    100                     cout<<dp[i][j][ALL_STATE-1]<<endl;
    101                     huisu(i , j , ALL_STATE-1);
    102                     print();
    103                     return 0;
    104                 }
    105             }
    106 
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    在vscode中显示空格和tab符号
    如何正确理解关键字"with"与上下文管理器
    HADOOP基本操作命令
    Ganglia环境搭建并监控Hadoop分布式集群
    关于分布式系统的数据一致性问题
    hadoop snapshot 备份恢复 .
    hadoop主节点(NameNode)备份策略以及恢复方法
    HDFS snapshot操作实战
    从 secondarynamenode 中恢复 namenode
    hadoop 通过distcp进行并行复制
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4735117.html
Copyright © 2020-2023  润新知