absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
POJ 3910 解题报告
数论专题-to do list

100753 A 解题报告

absi2011 posted @ Nov 25, 2015 11:15:12 PM in 刷题记录 with tags DP dijkstra 图论 CF Gym , 880 阅读

题目链接:http://codeforces.com/gym/100753/attachments/download/3533/2015-german-collegiate-programming-contest-gcpc-15-en.pdf

题目翻译:

给你一个无向图

你想去某些点玩,需要在这些点待一会儿

你可以任意走这些边,走每个边有个代价

你需要从0号点出发,访问所有你要玩的点并在那里停留,最后回到0号点

在你走的过程中,你可以打一个taxi(只能一个),然后移动到任何一个点

问:

1,能不能不用taxi来完成旅行?

2,如果不能,能不能用来完成旅行?

样例:

如那个图..

解法:

总时间去掉所有停留的时间

然后求最短路,找出p个点之间两两的距离(还有0和这p个点的距离)

写个状压dp,计算出最短距离(不用taxi)和用的(把两条路之间距离修改为T即可)

代码如下:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<math.h>
#include<time.h>
#include<vector>
#include<bitset>
#include<memory>
#include<utility>
#include<fstream>
#include<stdio.h>
#include<sstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct edge
{
    int y;
    int weight;
    edge * next;
};
edge * li[20005];
edge * new_edge()
{
    static edge a[200005];
    static int top=0;
    return &a[top++];
}
void inserts(int x,int y,int z)
{
    edge * t=new_edge();
    t->y=y;
    t->weight=z;
    t->next=li[x];
    li[x]=t;
}
void insert_edge(int x,int y,int z)
{
    inserts(x,y,z);
    inserts(y,x,z);
}
int dist[20005];
bool visit[20005];
void dijkstra(int s)
{
    memset(dist,-1,sizeof(dist));
    memset(visit,false,sizeof(visit));
    priority_queue<pair<int,int> > que;
    dist[s]=0;
    que.push(make_pair(0,s));
    for (;!que.empty();)
    {
        int now=que.top().second;
        que.pop();
        if (visit[now])
        {
            continue;
        }
        visit[now]=true;
        edge * t;
        for (t=li[now];t!=0;t=t->next)
        {
            if ((dist[t->y]==-1)||(dist[now]+t->weight<dist[t->y]))
            {
                dist[t->y]=dist[now]+t->weight;
                que.push(make_pair(-dist[t->y],t->y));
            }
        }
    }
}
int a[25];
int dis[25][25];
int dp[1<<15][25][2];
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,p,m,s,tt;
    scanf("%d%d",&n,&p);
    scanf("%d%d%d",&m,&s,&tt);
    int i;
    for (i=0;i<p;i++)
    {
        scanf("%d",&a[i]);
        int x;
        scanf("%d",&x);
        s-=x;
    }
    for (i=0;i<m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        insert_edge(x,y,z);
    }
    a[p]=0;
    for (i=0;i<=p;i++)
    {
        dijkstra(a[i]);
        int j;
        for (j=0;j<=p;j++)
        {
            dis[i][j]=dist[a[j]];
            if (dis[i][j]==-1)
            {
                puts("impossible");
                return 0;
            }
        }
    }
    for (i=0;i<(1<<p);i++)
    {
        int j;
        for (j=0;j<=p;j++)
        {
            dp[i][j][0]=999999999;
            dp[i][j][1]=999999999;
        }
    }
    dp[0][p][0]=0;
    for (i=0;i<(1<<p);i++)
    {
        int j;
        for (j=0;j<p;j++)
        {
            if (((1<<j)&i)==0) continue;
            int k;
            for (k=0;k<p;k++)
            {
                //from j to k
                if ((1<<k)&i) continue;
                dp[i^(1<<k)][k][0]=min(dp[i^(1<<k)][k][0],dp[i][j][0]+dis[j][k]);
                dp[i^(1<<k)][k][1]=min(dp[i^(1<<k)][k][1],dp[i][j][1]+dis[j][k]);
                dp[i^(1<<k)][k][1]=min(dp[i^(1<<k)][k][1],dp[i][j][0]+tt);
            }
            if (i==(1<<p)-1)
            {
                dp[i][p][0]=min(dp[i][p][0],dp[i][j][0]+dis[j][p]);
                dp[i][p][1]=min(dp[i][p][1],dp[i][j][1]+dis[j][p]);
                dp[i][p][1]=min(dp[i][p][1],dp[i][j][0]+tt);
            }
        }
        if (i==0)
        {
            int k;
            for (k=0;k<p;k++)
            {
                //from p to k
                dp[i^(1<<k)][k][0]=min(dp[i^(1<<k)][k][0],dp[i][j][0]+dis[p][k]);
                dp[i^(1<<k)][k][1]=min(dp[i^(1<<k)][k][1],dp[i][j][1]+dis[p][k]);
                dp[i^(1<<k)][k][1]=min(dp[i^(1<<k)][k][1],dp[i][j][0]+tt);
            }
        }
    }
    if (dp[(1<<p)-1][p][0]<=s)
    {
        printf("possible without taxi\n");
    }
    else if (dp[(1<<p)-1][p][1]<=s)
    {
        printf("possible with taxi\n");
    }
    else
    {
        printf("impossible\n");
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter