A - A Journey to Greece TSP

A - A Journey to Greece

题目大意:

给你一个包含 \(N\) 个点的无向图,必须访问到其中指定的 \(P\) 个节点,与此同时,还有一张 \(T\) 时间可以从当前点出发前往任意地点的车票,问是否能够在规定时间内访问完所有的指定点并回到出发点。如果可以不用车票输出“possible without taxi”,如果必须要车票输出“possible with taxi”,如果无法完成出“impossible”。
\(N<=2∗10^4,P<=15,M<=10^5\)

题解:

其实就是一个简单的 \(TSP\) 问题

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = (1<<15) + 10;
const int maxm = 2e5 + 10;
int dp[maxn][20][2];
// dp[i][j][k] 表示现在访问的状态是 i ,最后走的是第 j 个城市,是否坐了taxi
int p[20],t[20];
int head[maxm],to[maxm],nxt[maxm],w[maxm],cnt;
void add(int u,int v,int c){
    ++cnt,to[cnt] = v,w[cnt] = c,nxt[cnt] = head[u],head[u] = cnt;
    ++cnt,to[cnt] = u,w[cnt] = c,nxt[cnt] = head[v],head[v] = cnt;
}
struct node{
    int u,d;
    node(int u=0,int d=0):u(u),d(d){}
    bool operator<(const node&a)const{
        return a.d<d;
    }
};
int N,P,M,G,T;
bool vis[maxm];
int dis[20][maxm];
priority_queue<node>que;
void dij(int s){
    for(int i=0;i<=N;i++) vis[i] = 0,dis[s][i] = inf;
    while(!que.empty()) que.pop();
    que.push(node(p[s],0));
    dis[s][p[s]] = 0;
    while(!que.empty()){
        node x = que.top();que.pop();
        int u = x.u;
        if(vis[u]) continue;
        vis[u] = true;
        for(int i=head[u];i;i=nxt[i]){
            int v = to[i];
            if(dis[s][v]>dis[s][u]+w[i]){
                dis[s][v] = dis[s][u] + w[i];
                que.push(node(v,dis[s][v]));
            }
        }
    }
}
void debug(int x,int y,int z){
    printf("dp[%d][%d][%d]=%d\n",x,y,z,dp[x][y][z]);
}
int main() {
    scanf("%d%d%d%d%d", &N, &P, &M, &G, &T);
    for (int i = 1; i <= P; i++) scanf("%d%d", &p[i], &t[i]),p[i]++;
    for (int i = 1; i <= M; i++) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        u++, v++;
        add(u, v, c);
    }
    for (int i = 1; i <= P; i++) dij(i);
    memset(dp, inf, sizeof(dp));
    for(int i=1;i<=P;i++) {
        int tmp = 1 << (i - 1);
        dp[tmp][i][0] = t[i] + dis[i][1];
        dp[tmp][i][1] = t[i] + T;
    }
    int len = (1 << P);
    for (int s = 0; s < len; s++) {
        for (int j = 1; j <= P; j++) {
            int tmp1 = 1 << (j - 1);
            if (dp[s][j][0] >= inf && dp[s][j][1] >= inf) continue;
            if ((s | tmp1) != s) continue;
            for (int k = 1; k <= P; k++) {
                int tmp2 = 1 << (k - 1);
                if ((tmp2 | s) == s) continue;
                tmp2 |= s;
                dp[tmp2][k][0] = min(dp[tmp2][k][0], dp[s][j][0] + dis[j][p[k]] + t[k]);
                dp[tmp2][k][1] = min(dp[tmp2][k][1], dp[s][j][1] + dis[j][p[k]] + t[k]);
                dp[tmp2][k][1] = min(dp[tmp2][k][1], dp[s][j][0] + T + t[k]);
//                debug(s,j,0);
//                debug(s,j,1);
//                printf("dp[%d][%d][%d]=%d\n",tmp2,k,0,dp[tmp2][k][0]);
//                printf("dp[%d][%d][%d]=%d\n",tmp2,k,1,dp[tmp2][k][1]);
            }
        }
    }
    int f1 = 0,f2 = 0;
    for(int j=1;j<=P;j++){
        if(dp[len-1][j][0]+dis[j][1]<=G) f1 = 1;
//        debug(len-1,j,0);
//        debug(len-1,j,1);
        if(dp[len-1][j][0]+T<=G) f2 = 1;
        if(dp[len-1][j][1]+dis[j][1]<=G) f2 = 1;
//        printf("fir : dis[%d][%d]=%d T = %d\n",j,1,dis[j][1],T);
    }
    if(f1) printf("possible without taxi\n");
    else if(f2) printf("possible with taxi\n");
    else printf("impossible\n");
    return 0;
}
posted @ 2021-03-21 21:03  EchoZQN  阅读(22)  评论(0编辑  收藏  举报