100753 A 解题报告
题目链接: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;
}
评论 (0)