luo's oj P1974 宝藏(treasure)

传送门

分析

noip day2 关键题状压dp

首先这是一道裸题就是MST的dp上加了一点要求;然而我并不会MST的dp于是生推QAQ;
效率(n^4)hhh其实是我也不知道这个记忆化剪枝太玄学了(划掉)
代码其实很简单的(划掉)枚举以所有的点为起点然后记忆化搜一遍并根新答案,
话说为什么跟普及组的T3这么像,当时就没水过(QAQ划掉)

#include<bits/stdc++.h>
#define N 15
#define INF 1e9
using namespace std;
int p[N][N],g[N][N],d[N],f[30005],ans=INF,n,m;
void dfs(int x){
    for(int i=1;i<=n;i++)
        if((1<<i-1)&x)//判断是否取过
            for(int j=1;j<=n;j++)
                if(!(1<<(j-1)&x)&&p[i][j]&&f[1<<(j-1)|x]>f[x]+d[i]*g[i][j]){//判断能否跟新
                    int t=d[j];
                    d[j]=d[i]+1;
                    f[1<<(j-1)|x]=f[x]+d[i]*g[i][j];//更新,说是转移也可以
                    dfs(1<<(j-1)|x);//继续搜
                    d[j]=t;//回溯
                }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            g[i][j]=INF;
    for(int i=1;i<=m;i++){
        int x,y,v;
        scanf("%d%d%d",&x,&y,&v);
        p[x][y]=p[y][x]=1;
        if(g[x][y]>v)g[x][y]=g[y][x]=v;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)d[j]=15;
        for(int j=1;j<(1<<n);j++)f[j]=INF;
        d[i]=1;f[1<<(i-1)]=0;
        dfs(1<<(i-1));
        ans=min(ans,f[(1<<n)-1]);
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36316033/article/details/81077229
OJ