Mr. Rito Post Office [Aizu-2200] [图论] [DP]

题意:
你是某个岛国(ACM-ICPC Japan )上的一个苦逼程序员,你有一个当邮递员的好基友利腾桑遇到麻烦了:全岛有一些镇子通过水路和旱路相连,走水路必须要用船,在X处下船了船就停在X处。而且岛上只有一条船,下次想走水路还是得回到X处才行;两个镇子之间可能有两条以上的水路或旱路;邮递员必须按照清单上的镇子顺序送快递(镇子可能重复,并且对于重复的镇子不允许一次性处理,比如ABCB的话B —定要按顺序走两次才行)。
测试数据有多组:
N M
xl yl tl sll
x2 y2 t2 sl2
XM yM tM SIM
R
Zl Z2 ... ZR
N (2 <= N <= 200)是镇子的数星,M (1 <= M <= 10000)是旱路和水路合计的数量。
从第2行到第M+1行是路径的描述,路径连接xi yi两地,路径花费ti (1 s ti s 1000)时间,sli为L时表示是旱路,S时表示是水路。
可能有两条及以上路径连接两个镇子,并且路径都是双向的。
M + 2行的R是利腾需要去的镇子的数量,M + 3是利腾需要去的镇子的编号
初始状态利腾和船都在第一个镇子,且肯定有方法达到需要去的镇子。
测试数据为0 0的时候表示终止。

样例输入

3 3
1 2 5 L
1 2 7 S
2 3 11 S
3
1 2 3
5 5
1 2 15 L
2 3 10 L
4 5 7 L
1 3 30 S
3 4 100 S
5
1 3 5 4 1
0 0

样例输出

   18

   269

分析

这道dp题还是比较容易想的,不过有一个坑人的地方!

因为要转移的参考量,一是当前位置,二是船的位置,那么设dp[i][j]为走到第i个城市,船停在j

那么状态转移方程就是dp[i][j]=min(dp[i-1][k]+l[id[i-1]][k]+s[k][j]+l[j][id[i]],dp[i][j]);

但是j==k的时候,不要去移船!dp[i][j]=min(dp[i-1][k]+l[id[i-1][id[i]],dp[i][j]);

代码

 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register ll
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll long long
14 #define inf (1<<29)
15 #define maxn 205
16 #define maxr 1005
17 using namespace std;
18 ll n,m,cnt;
19 ll l[maxn][maxn],s[maxn][maxn],id[maxr],dp[maxr][maxn];
20 inline ll read()
21 {
22     ll x=0,f=1;char c=getchar();
23     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
24     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
25     return x*f;
26 }
27 
28 void DP()
29 {
30     memset(dp,63,sizeof(dp));
31     dp[1][id[1]]=0;
32     rep(i,2,cnt)
33         rep(j,1,n)
34             rep(k,1,n)
35             {
36                 if(j!=k) //
37                     dp[i][j]=min(dp[i-1][k]+l[id[i-1]][k]+s[k][j]+l[j][id[i]],dp[i][j]);
38                 else
39                     dp[i][j]=min(dp[i-1][k]+l[id[i-1]][id[i]],dp[i][j]);
40             }
41     ll mn=inf;
42     rep(i,1,n)    mn=min(mn,dp[cnt][i]);
43     cout<<mn<<endl;
44 }
45 
46 int main()
47 {
48     char opt;
49     while(1)
50     {
51         n=read(),m=read();
52         if(!n)    return 0;
53         rep(i,1,n)rep(j,1,n)    l[i][j]=s[i][j]=inf;
54         rep(i,1,n)                l[i][i]=s[i][i]=0;
55         for(RG i=1,a,b,c;i<=m;i++)
56         {
57             a=read(),b=read(),c=read();opt=getchar();
58             if(opt=='L')    l[a][b]=l[b][a]=c;
59             else            s[a][b]=s[b][a]=c;
60         }
61         rep(k,1,n)rep(i,1,n)rep(j,1,n)    l[i][j]=min(l[i][j],l[i][k]+l[k][j]),s[i][j]=min(s[i][j],s[i][k]+s[k][j]);
62         cnt=read();
63         rep(i,1,cnt)    id[i]=read();
64         DP();
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/ibilllee/p/9239869.html