【LDU】 Week2自测 Disney‘s FastPass | 状压dp、Floyd

这题是hdu 4114...

跟着19的打了打周测,发现个好题

写了写还wa了一发

题目大意:

给出n个点,k个要旅游的景点,然后给出k个景点的信息(位置,t,ft,门票所在地点),t于ft表示,如果参观这个经典使用门票则需要ft时间,否则需要t时间。问参观完所有经典并且返回来的最短路。

题目思路:

经典套路状压dp了,类似于状压dp求哈密尔顿回路

由于涉及到两个状态,所以设状态:i,k分别为门票的状态二进制 与 访问状态的二进制

然后就直接进行状压dp就好了,注意的是最短路最好提前处理好,点数比较小Floyd就好了

Code:

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
using namespace std;
const int N=1e3+15;
typedef long long ll;
const ll INF = 1e18;
double PI=acos(-1.0);
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
const int maxn=1e6+5;
ll n,m,p;
ll mp[55][55];
ll dp[55][1<<8][1<<8];
ll f[55];
int pos[55],ft[55],t[55];
void _inint(){
    for(int i=0;i<55;i++){
        for(int k=0;k<55;k++){
            if(i==k) mp[i][k] = 0;
            else mp[i][k] = INF;
        }
    }
    for(int i=0;i<55;i++){
        for(int k=0;k<1<<8;k++){///游览状态
            for(int j=0;j<1<<8;j++){
                dp[i][k][j] = INF;
            }
        }
    }
    memset(f,0,sizeof(f));
    dp[1][0][0] = 0;///初始状态
}
int main()
{
    int cas = 0;
    int T;scanf("%d",&T);
    while(T--){
        _inint();
        read(n);read(m);read(p);
        for(int i=1;i<=m;i++){
            ll x,y,w;read(x);read(y);read(w);
            mp[x][y] = min(mp[x][y],w);
            mp[y][x] = min(mp[y][x],w);
        }
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                for(int j=1;j<=n;j++)
                    mp[k][j] = min(mp[k][i]+mp[i][j],mp[k][j]);
        for(int i=0;i<p;i++){
            int x;
            scanf("%d%d%d%d",&pos[i],&t[i],&ft[i],&x);
            while(x--){
                ll y;read(y);
                f[y] |= 1<<i;
            }
        }
        ll ans = INF;
        for(int i=0;i<(1<<p);i++){///访问景点
            for(int k=0;k<(1<<p);k++){///门票
                for(int j=1;j<=n;j++){
                    if(dp[j][i][k] != INF){

                        if(i == ((1<<p)-1)) ans = min(ans,dp[j][i][k]+mp[j][1]);
                        for(int aim=0;aim<p;aim++){
                            if((i&(1<<aim)) == 0){///没去过
                                if(k&(1<<aim)) ///有门票
                                    dp[pos[aim]][i^(1<<aim)][k|f[pos[aim]]] = min(dp[pos[aim]][i^(1<<aim)][k|f[pos[aim]]],dp[j][i][k]+mp[j][pos[aim]]+ft[aim]);
                                else dp[pos[aim]][i^(1<<aim)][k|f[pos[aim]]] =min(dp[pos[aim]][i^(1<<aim)][k|f[pos[aim]]],dp[j][i][k]+mp[j][pos[aim]]+t[aim]);
                            }
                        }
                        ///不去游玩 到处跑
                        for(int aim=1;aim<=n;aim++){
                            dp[aim][i][k|f[aim]] = min(dp[aim][i][k|f[aim]],dp[j][i][k]+mp[aim][j]);
                        }

                    }

                }
            }
        }
        printf("Case #%d: %lld\n",++cas,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107283110