1.注意到K=20,这样的数据范围让人想到状压DP,而且允许进行K次Dijkstra算法。
2.题目中“公司规定了其中某些小区送餐的先后顺序,比如i小区的餐必须在给j小区送餐前送到”释放出明显的拓扑排序信号。
3.设 f[i][j] 表示在i表示的状态下终点为j时的最小路程和,容易写出状态转移方程:
f[en][j]=min{f[st][k]+dis[k][j]} ,其中dis[k][j]表示k到j的最短距离,这个可以用最短路算法处理。满足拓扑序列关系时才可以转移。
#include<stdio.h>
#include<stack>
#include<queue>
#define ll long long
#define MAXN 20005
#define MAXM 400005
#define Min(x,y) ((x<y)?(x):(y))
using namespace std;
int N,M,K,T,ok[25],Lim;
ll f[1050000][25],Ans=2e9;
inline int _R()
{
char s=getchar();int v=0,sign=0;
while((s!='-')&&(s>57||s<48))s=getchar();
if(s=='-')sign=1,s=getchar();
for(;s>47&&s<58;s=getchar())v=v*10+s-48;
if(sign)v=-v;
return v;
}
int en[MAXM],nex[MAXM],las[MAXN],len[MAXM],tot;
void ADD(int x,int y,int z)
{
en[++tot]=y;
nex[tot]=las[x];
las[x]=tot;
len[tot]=z;
}
int En[MAXM],Nex[MAXM],Las[MAXN],Tot;
void add(int x,int y)
{
En[++Tot]=y;
Nex[Tot]=Las[x];
Las[x]=Tot;
}
ll dis[25][MAXN];
void Dijkstra(int s,int p)
{
int i,x,y;
ll z;
priority_queue<pair<ll,int> >Q;
for(i=1;i<=N;i++)dis[p][i]=2e9;
dis[p][s]=0;
Q.push(make_pair(0,s));
while(Q.size())
{
x=Q.top().second;
z=Q.top().first;
Q.pop();
if(dis[p][x]!=-z)continue;
for(i=las[x];i;i=nex[i])
{
y=en[i];
if(dis[p][y]>dis[p][x]+len[i])
{
dis[p][y]=dis[p][x]+len[i];
Q.push(make_pair(-dis[p][y],y));
}
}
}
}
int D[400];
stack<int>S;
int main()
{
int i,j,k,x,y,z,cnt=0,Size;
N=_R();M=_R();K=_R();
for(i=1;i<=M;i++)
{
x=_R();y=_R();z=_R();
ADD(x,y,z);
ADD(y,x,z);
}
T=_R();
for(i=1;i<=T;i++)
{
x=_R();y=_R();
add(x,y);
D[y]++;
}
for(i=1;i<=K+1;i++)Dijkstra(i,i);
for(i=2;i<=K+1;i++)if(!D[i])S.push(i);
while(S.size())
{
x=S.top();S.pop();
for(i=Las[x];i;i=Nex[i])
{
y=En[i];
D[y]--;
ok[y]=ok[y]|ok[x]|(1<<x-2);
if(!D[y])S.push(y);
}
}
//ok[i]表示i要加入时的前提条件
Lim=(1<<K)-1;
for(i=0;i<=Lim;i++)
for(j=0;j<=K+1;j++)f[i][j]=2e9;
f[0][1]=0;
for(i=0;i<=Lim;i++)
{
for(j=1;j<=K+1;j++)
{
if(f[i][j]==2e9)continue;
for(k=2;k<=K+1;k++)
{
if(((i&ok[j])!=ok[j]))continue;
f[i|(1<<k-2)][k]=Min((f[i|(1<<k-2)][k]),(f[i][j]+dis[j][k]));
}
}
}
for(i=1;i<=K+1;i++)Ans=Min(Ans,(f[Lim][i]+dis[i][N]));
printf("%lld",Ans);
}

本文介绍了一道算法题的解决思路,通过状压DP和拓扑排序的方法来求解带有限制条件的最短路径问题。文章详细阐述了如何利用状态压缩技术将问题转化为适合动态规划的形式,并结合拓扑排序确保了送餐顺序符合公司的规定。

699

被折叠的 条评论
为什么被折叠?



