$dp[i][state]$ 表示以$i$为根,指定集合中的点的连通状态为state的生成树的最小总权值

有两种转移方向:

1、先通过连通状态的子集进行转移。

2、在当前枚举的连通状态下,对该连通状态进行松弛操作。

P4294 [WC2008]游览计划

注意景点的个数不超过10个。

$dp[i][j][state]$ 表示在$[i, j]$这个点与state中对应点连通的最小代价。

那么就可以用状压DP + spfa求解。

由于要输出方案,可以记录每个状态的前一个状态,最后dfs跑一遍就行了。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_set>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 12;
            int a[maxn][maxn];
            int dp[maxn][maxn][1055];
            struct node{
                int x, y, state;
            } pre[maxn][maxn][1055];

            queue<pii>que;
            int nx[4][2] = {
                {0, 1}, {1, 0},{-1,0},{0,-1}
            };
            int n,m;
            int vis[maxn][maxn];
            void spfa(int now) {
                while(!que.empty()) {
                    pii tmp = que.front(); que.pop();
                    for(int i=0; i<4; i++) {
                        int x = tmp.fi + nx[i][0];
                        int y = tmp.se + nx[i][1];
                        if(x < 1 || x > n || y < 1 || y > m) continue;
                        if(dp[x][y][now] > dp[tmp.fi][tmp.se][now] + a[x][y]) {
                            dp[x][y][now] = dp[tmp.fi][tmp.se][now] + a[x][y];
                            pre[x][y][now] = node{tmp.fi, tmp.se, now};
                            if(!vis[x][y]) {
                                que.push(pii(x, y));
                                vis[x][y] = 1;
                            }
                        }
                    }
                    vis[tmp.fi][tmp.se] = 0;
                }
            }
            void dfs(int x, int y, int now) {
                if(x == 0 || y == 0) return;
                vis[x][y] = 1;
                node tmp = pre[x][y][now];
                dfs(tmp.x, tmp.y, tmp.state);
                if(tmp.x == x && tmp.y == y)
                    dfs(tmp.x, tmp.y, now - tmp.state);
            }
int main(){
            scanf("%d%d", &n, &m);
            memset(dp, inf, sizeof(dp));
            int num = 0;
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    scanf("%d", &a[i][j]);
                    if(a[i][j] == 0) {
                        dp[i][j][(1<<num)] = 0;
                        num++;
                    }
                }
            }
            int all = (1<<num) - 1;

            for(int state = 0; state <= all; state ++) {
                for(int i=1; i<=n; i++) {
                    for(int j=1; j<=m; j++) {
                        for(int s0 = (s0-1) & state; s0; s0 = (s0-1) & state) {

                            if(dp[i][j][state] > dp[i][j][s0] + dp[i][j][state - s0] - a[i][j]) {
                                dp[i][j][state] = dp[i][j][s0] + dp[i][j][state - s0] - a[i][j];
                                pre[i][j][state] = node{i, j, s0};

                            }
                        }
                        if(dp[i][j][state] < inf) que.push(pii(i, j)), vis[i][j] = 1;
                    }
                }
                spfa(state);
            }
            int ax, ay, mn = inf;
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    if(dp[i][j][all] < mn) {
                        mn = dp[i][j][all];
                        ax = i;
                        ay = j;
                    }
                }
            }
            printf("%d\n", mn);
            memset(vis, 0, sizeof(vis));
            dfs(ax, ay, all);
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    if(a[i][j] == 0) printf("x");
                    else if(vis[i][j]) printf("o");
                    else printf("_");
                }
                puts("");
            }
            return 0;
}
View Code

相关文章:

  • 2021-11-27
  • 2022-02-27
  • 2021-08-12
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-08-29
  • 2022-12-23
  • 2021-11-15
  • 2021-05-25
相关资源
相似解决方案