2 条题解

  • 0
    @ 2025-10-8 17:13:39
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    typedef pair<int, int> PII;
    int a[15][15], p[15], dp[105][5000], pre[105][5000];
    bool ans[15][15][5000], an[15][15];
    vector<PII> e[105];//e[i].second 是没用的但我懒得改了反正空间管够 
    int n, m, k;
    int number(int x, int y) {
        return (x-1)*m + y - 1;
    }
    PII enc(int p) {
        int x = p/m + 1, y = p%m + 1;
        return {x, y};
    }
    bool vis[105];
    int val[105];
    void dij(int S) {
        memset(vis, 0, sizeof(vis));
        priority_queue<PII, vector<PII>, greater<PII>> q;
        for(int i = number(1, 1); i <= number(n, m); i++) if(dp[i][S] != 0x3f3f3f3f) q.push({dp[i][S], i});
        while(!q.empty()) {
            int x = q.top().second; q.pop();
            if(vis[x]) continue;
            for(PII t : e[x]) {
                int y = t.first, w = t.second;
                if(dp[y][S] > dp[x][S] + val[y]) {
                    dp[y][S] = dp[x][S] + val[y];
                    pre[y][S] = x;
                    q.push({dp[y][S], y});
                }
            }
        }
    }
    void road(int q, int S) {
        PII p = enc(q);
        int x = p.first, y = p.second;
        if(ans[x][y][S]) return;
        ans[x][y][S] = 1;
        an[x][y] = 1;
        if(pre[q][S] != -1 && dp[pre[q][S]][S] + val[q] == dp[q][S]) {
            road(pre[q][S], S);
        }
        for(int s = S; s; s = ((s-1) & S)) {
            if(dp[q][S] == dp[q][s] + dp[q][S^s] - val[q]) {
                road(q, s); road(q, S^s);
                break;
            }
        }
    }
    signed main() {
        ios::sync_with_stdio(0); cin.tie(0);
        cin >> n >> m;
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
        memset(dp, 0x3f, sizeof(dp));
        memset(pre, -1, sizeof(pre));
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) {
            if(i > 1) e[number(i, j)].push_back({number(i-1, j), a[i-1][j]});
            if(i < n) e[number(i, j)].push_back({number(i+1, j), a[i+1][j]});
            if(j > 1) e[number(i, j)].push_back({number(i, j-1), a[i][j-1]});
            if(j < m) e[number(i, j)].push_back({number(i, j+1), a[i][j+1]});
            if(a[i][j] == 0) {
                p[++k] = number(i, j);
                dp[number(i, j)][1 << k-1] = 0;
            } val[number(i, j)] = a[i][j];
        }
        for(int S = 0; S < (1 << k); S++) {
            for(int s = S; s; s = ((s-1) & S)) {
                for(int i = number(1, 1); i <= number(n, m); i++) {
                    dp[i][S] = min(dp[i][S], dp[i][s] + dp[i][S^s] - val[i]);
                }
            }
            dij(S);
        }
        if(k == 0) cout << 0 << endl;
        else cout << dp[p[1]][(1 << k)-1] << endl;
        if(k) road(p[1], (1 << k)-1);
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(a[i][j])
                if(an[i][j]) cout << 'o';
                else cout << '_';
                else cout << 'x';
            }
            cout << endl;
        }
        return 0;
    }
    
    • 0
      @ 2025-10-8 17:13:28
      #include<bits/stdc++.h>
      #define int long long
      using namespace std;
      typedef pair<int,int> PII;
      int a[15][15],p[15],dp[105][5000],pre[105][5000];
      bool ans[15][15][5000],an[15][15];
      vector<PII>e[105];//e[i].second 是没用的但我懒得改了反正空间管够 
      int n,m,k;
      int number(int x,int y){
          return (x-1)*m+y-1;
      }
      PII enc(int p){
          int x=p/m+1,y=p%m+1;
          return {x,y};
      }
      bool vis[105];
      int val[105];
      void dij(int S){
          memset(vis,0,sizeof(vis));
          priority_queue<PII,vector<PII>,greater<PII>>q;
          for(int i=number(1,1);i<=number(n,m);i++)if(dp[i][S]!=0x3f3f3f3f)q.push({dp[i][S],i});
          while(!q.empty()){
              int x=q.top().second;q.pop();
              if(vis[x])continue;
              for(PII t:e[x]){
                  int y=t.first,w=t.second;
                  if(dp[y][S]>dp[x][S]+val[y]){
                      dp[y][S]=dp[x][S]+val[y];
                      pre[y][S]=x;
                      q.push({dp[y][S],y});
                  }
              }
          }
      }
      void road(int q,int S){
          PII p=enc(q);
          int x=p.first,y=p.second;
          if(ans[x][y][S])return;
          ans[x][y][S]=1;
          an[x][y]=1;
          if(pre[q][S]!=-1&&dp[pre[q][S]][S]+val[q]==dp[q][S]){
              road(pre[q][S],S);
          }
          for(int s=S;s;s=((s-1)&S)){
              if(dp[q][S]==dp[q][s]+dp[q][S^s]-val[q]){
                  road(q,s);road(q,S^s);
                  break;
              }
          }
      }
      signed main(){
          ios::sync_with_stdio(0);cin.tie(0);
          cin>>n>>m;
          for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
              cin>>a[i][j];
          }
          memset(dp,0x3f,sizeof(dp));
          memset(pre,-1,sizeof(pre));
          for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
              if(i>1)e[number(i,j)].push_back({number(i-1,j),a[i-1][j]});
              if(i<n)e[number(i,j)].push_back({number(i+1,j),a[i+1][j]});
              if(j>1)e[number(i,j)].push_back({number(i,j-1),a[i][j-1]});
              if(j<m)e[number(i,j)].push_back({number(i,j+1),a[i][j+1]});
              if(a[i][j]==0){
                  p[++k]=number(i,j);
                  dp[number(i,j)][1<<k-1]=0;
              }val[(number(i,j))]=a[i][j];
          }
          for(int S=0;S<(1<<k);S++){
              for(int s=S;s;s=((s-1)&S)){
                  for(int i=number(1,1);i<=number(n,m);i++){
                      dp[i][S]=min(dp[i][S],dp[i][s]+dp[i][S^s]-val[i]);
                  }
              }
              dij(S);
          }
          if(k==0)cout<<0<<endl;
          else cout<<dp[p[1]][(1<<k)-1]<<endl;
          if(k)road(p[1],(1<<k)-1);
          for(int i=1;i<=n;i++){
              for(int j=1;j<=m;j++){
                  if(a[i][j])
                  if(an[i][j])cout<<'o';
                  else cout<<'_';
                  else cout<<'x';
              }
              cout<<endl;
          }
          return 0;
      }
      • 1

      *【状压DP:最小斯坦纳树】游览计划[WC2008]

      信息

      ID
      7409
      时间
      1000ms
      内存
      128MiB
      难度
      8
      标签
      递交数
      25
      已通过
      5
      上传者