题意
简单来说就是求1,m的最短路,但是现在一共要走n次,也就是n天每天走一次。在某些天的时间里,有一些点不可以走,然后求走n次的最短路。
做题之前:
wk,这题目啥意思啊,让我读一读啊…
?读完一遍了,啥意思啊。题目没抄全吧。
看了下别人的分析之后,原来是这个意思啊!
遂码…
写完代码之后:
怎么不过样例啊???
遂改。
怎么全爆了啊,遂重码
终于过样例了。
提交代码时:
CE了啊????
换了头文件后。
还是CE啊????
什么?BZOJ不能把结构体写在函数里面???
终于AC。
分析:
如果我们假设第i天到第j天的最短路的权值求好了,
【看电影去了,看完电影再来更新】
【看完了,哥斯拉2真好看,哥斯拉nb(振声)】
继续开始分析:
设第i天到第j天的权值为dp[i][j],那么显然答案就是dp[1][n],通过观察我们可以很容易的发现,这不就是个区间dp嘛!于是我们就像区间dp那样转移一下就好了:
- 枚举长度
- 枚举起点
- 枚举断点
于是,我们的转移方程就是这个样子:
for(int l=2;l<=n;l++)
{
for(int i=1;i+l-1<=n;i++)
{
int j = i+l-1;
for(int k=i;k<j;k++)
{
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+K);
}
}
}
(很简单吧)
转移方程很显然,我们在第k天变换了路线,那么我们就需要加上K,因为每一次变换我们需要花费K点。(注意大小写)
那么dp[i][j]怎么求呢?
如果第i天到第j天没有什么港口不能使用的话,很显然dp[i][j]就是1到m的最短路了。
那么如果在最短路的港口不能用了咋办呢,我们当它不存在就行了,具体看这里:
for(int i=0;i<G[nw.now].size();i++)
{
int v = G[nw.now][i].to;
int w = G[nw.now][i].cost;
if(!isok(v,s,t)) continue;
if(dis[v]>dis[nw.now]+w)
{
dis[v] = dis[nw.now]+w;
q.push({v,dis[v]});
}
}
这个是更新路径的时候的代码部分,如果第s天到第t天的v不能走的话,我们就当它不存在。
于是dp[i][j]就可以求出来了。
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
dp[i][j] = dijkstra(i,j);
}
}
于是我们就把这道题做完了。
还是贴一下代码吧:
/**************************************************************
Problem: 1003
User: ACgay_caoyue
Language: C++
Result: Accepted
Time:84 ms
Memory:1640 kb
****************************************************************/
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 210;
struct edge
{
int to;
int cost;
};
struct node
{
int now;
int cost;
bool operator<(const node &rhs)const
{
return cost>rhs.cost;
}
};
vector<edge> G[maxn];
int ban[maxn][maxn];
int n,m,K,e,d;
int dis[maxn];
int dp[maxn][maxn];
bool isok(int x,int s,int t)
{
for(int i=s;i<=t;i++)
{
if(ban[x][i]) return false;
}
return true;
}
int dijkstra(int s,int t)
{
memset(dis,INF,sizeof(dis));
dis[1] = 0;
priority_queue<node> q;
q.push({1,dis[1]});
while(!q.empty())
{
node nw = q.top();
q.pop();
if(dis[nw.now]<nw.cost) continue;
for(int i=0;i<G[nw.now].size();i++)
{
int v = G[nw.now][i].to;
int w = G[nw.now][i].cost;
if(!isok(v,s,t)) continue;
if(dis[v]>dis[nw.now]+w)
{
dis[v] = dis[nw.now]+w;
q.push({v,dis[v]});
}
}
}
return dis[m]==INF?INF:dis[m]*(t-s+1);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&K,&e);
for(int i=0;i<e;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
G[x].pb({y,w});
G[y].pb({x,w});
}
scanf("%d",&d);
for(int i=0;i<d;i++)
{
int p,x,y;
scanf("%d%d%d",&p,&x,&y);
for(int j=x;j<=y;j++) ban[p][j] = 1;
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
dp[i][j] = dijkstra(i,j);
}
}
for(int l=2;l<=n;l++)
{
for(int i=1;i+l-1<=n;i++)
{
int j = i+l-1;
for(int k=i;k<j;k++)
{
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+K);
}
}
}
printf("%d\n",dp[1][n]);
return 0;
}