思路就是dijkstra找出最短路,dfs比较每一个最短路。
dijkstra可以找出每个点的前一个点, 所以dfs搜索比较的时候怎么处理携带和带走的数量就是关键,考虑到这个携带和带走和路径顺序有关,所以可以用下面的写法,看代码就可以了。
最开始的时候是想用一个偏动态规划的写法做,但是因为题目的显示,既要带去的车数量最少,又要求从一个点带走的车数量最少,所以如果过动规的话,对于一个点的多个最短路,就会选择带去数量最少,带走车数最少的路径,但是如果这个点后面的点的车辆数少一标准量的一半的话,前面带的是最少的,这样相当于携带的车的数量就多了,这样就矛盾了。
当时挺纠结的,因为只写过一道类型的题,还是用动规的写法写的,那个权值只有两个,也是pat的题,这个主要是权值矛盾了, 所以不能用动规的思想写。
#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int g[maxn][maxn];
vector<int> pre[maxn];
int C,N,M,SP;
int vis[maxn],num[maxn],d[maxn];
void dijkstra()
{
d[0]=0;
for (int i=0;i<N;i++) {
int u=-1,tmp=INF;
for (int j=0;j<=N;j++) {
if (!vis[j]&&d[j]<tmp) {
tmp=d[j];
u=j;
}
}
if (u==-1) break;
vis[u]=1;
for (int j=0;j<=N;j++) {
if (j==u) {
continue;
}
if (d[u]+g[u][j]<d[j]) {
d[j]=d[u]+g[u][j];
pre[j].clear();
pre[j].push_back(u);
}
else if (d[u]+g[u][j]==d[j]) {
pre[j].push_back(u);
}
}
}
}
int path[maxn],acnt=0;
int ansn=INF,anst=INF,ansp[maxn];
void dfs(int u,int need,int take,int cnt)
{
path[cnt]=u;
if (u==0) {
// for (int i=0;i<cnt;i++) {
// printf("%d ",path[i]);
// }
// puts("");
// printf("need %d take %d
",need,take);
if (need<ansn) {
ansn=need;
anst=take;
acnt=cnt;
for (int i=0;i<cnt;i++) {
ansp[i]=path[i];
}
}
else if (need==ansn) {
if (take<anst) {
anst=take;
acnt=cnt;
for (int i=0;i<cnt;i++) {
ansp[i]=path[i];
}
}
}
return ;
}
if (num[u]==C/2) {}
else if (num[u]>C/2) {
if (need>0) {
if (num[u]-C/2>=need) {
take+=num[u]-C/2-need;
need=0;
}
else need-=num[u]-C/2;
}
else take+=num[u]-C/2;
}
else need+=C/2-num[u];
int sz=pre[u].size();
for (int i=0;i<sz;i++) {
dfs(pre[u][i],need,take,cnt+1);
}
}
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d%d%d",&C,&N,&SP,&M);
for (int i=1;i<=N;i++) {
scanf("%d",&num[i]);
}
memset(g,INF,sizeof(g));
for (int i=0;i<=N;i++) {
g[i][i]=0;
d[i]=INF;
}
int u,v,c;
for (int i=0;i<M;i++) {
scanf("%d%d%d",&u,&v,&c);
g[u][v]=c;
g[v][u]=c;
}
dijkstra();
// for (int i=1;i<=N;i++) {
// printf("%d ",d[i]);
// }
// puts("");
// for (int i=1;i<=N;i++) {
// printf("%d:
",i);
// for (int j=0;j<pre[i].size();j++) {
// printf("%d ",pre[i][j]);
// }
// printf("
");
// }
dfs(SP,0,0,0);
printf("%d %d",ansn,0);
for (int i=acnt-1;i>=0;i--) {
printf("->%d",ansp[i]);
}
printf(" %d
",anst);
return 0;
}