题目大意:给出N个城市m条路(有向路),两个城市之间可能连有多条路,经过一条从城市ai到bi的路i的付费方式有两种,如果之前到过城市ci则付费Pi,否则就在到达bi时付费Ri,问从城市1到城市N的最小代价
输入:N m
第i条路的描述(共m行, ai, bi, ci, Pi, Ri (1 ≤ m, N ≤ 10, 0 ≤ Pi , Ri ≤ 100, Pi ≤ Ri))
输出:最小代价(如果没有从1到N的路线则输出impossible)
分析:dfs+“闸数”技巧
最优路径中可能会存在环,也就是说可能会访问某个节点多次。因为N<=10,所以任意一个点最多存在于四个环里,也就是最多访问4次,这个次数被称为闸数(这个数到底是几有待考察,好多结题报告都不一样,而且没有解释理由)。将bool vis[]这个标记数组改为int vis[]即可。
代码:转载自http://blog.csdn.net/lyy289065406/article/details/6689310
- #include<iostream>
- using namespace std;
- int n; //城市数
- int m; //道路数
- int vist[11]; //记录城市的访问次数,每个城市最多经过3次
- int MinCost; //最小总花费
- struct
- {
- int a,b,c,p,r;
- }road[11]; //每条道路的付费规则
- void DFS(int a,int fee) //a:当前所在城市,fee:当前方案的费用
- {
- if(a==n && MinCost>fee)
- {
- MinCost=fee;
- return;
- }
- for(int i=1;i<=m;i++) //枚举道路
- {
- if(a==road[i].a && vist[ road[i].b ]<=3)
- {
- int b=road[i].b;
- vist[b]++;
- if(vist[ road[i].c ])
- DFS(b,fee+road[i].p);
- else
- DFS(b,fee+road[i].r);
- vist[b]--; //回溯
- }
- }
- return;
- }
- int main(void)
- {
- while(cin>>n>>m)
- {
- memset(vist,0,sizeof(vist));
- vist[1]=1; //从城市1出发,因此预记录到达1次
- MinCost=2000;
- for(int i=1;i<=m;i++)
- cin>>road[i].a>>road[i].b>>road[i].c>>road[i].p>>road[i].r;
- DFS(1,0);
- if(MinCost==2000)
- cout<<"impossible"<<endl;
- else
- cout<<MinCost<<endl;
- }
- return 0;
- }