A network of m roads connects N cities (numbered from 1 to N). There may be more than one road connecting one city with another. Some of the roads are paid. There are two ways to pay for travel on a paid road i from city ai to city bi:
- in advance, in a city ci (which may or may not be the same as ai);
- after the travel, in the city bi.
The payment is Pi in the first case and Ri in the second case.
Write a program to find a minimal-cost route from the city 1 to the city N.
The first line of the input contains the values of N and m. Each of the following m lines describes one road by specifying the values of ai, bi, ci, Pi, Ri (1 ≤ i ≤ m). Adjacent values on the same line are separated by one or more spaces. All values are integers, 1 ≤ m, N ≤ 10, 0 ≤ Pi , Ri ≤ 100, Pi ≤ Ri (1 ≤ i ≤ m).
The first and only line of the file must contain the minimal possible cost of a trip from the city 1 to the city N. If the trip is not possible for any reason, the line must contain the word ‘impossible’.
4 5 1 2 1 10 10 2 3 1 30 50 3 4 3 80 80 2 1 2 10 10 1 3 2 10 50Sample Output
110
题解:
一开始看错题了,wa了好多次,真是浪费时间。
这个题目,状态十分显然,dp[i][s]表示处于节点i,当前经过点的集合为s的最小花费,那么转移就是枚举边转移就可以了,注意,如果可以用情况1就必须用情况1.
初始化的时候都为inf,让他们不能更新其他状态,然后这个有后效性,必须spfa。
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #include <queue> #define MANXN 15 #define MAXNM 2100 #define ll long long using namespace std; int dp[MANXN][1<<MANXN],have[MANXN][1<<MANXN]; int n,m,num=0,inf; struct edge{ int first; int next; int to,c,p,r; }a[MAXNM*2]; struct heapnode{ int id;ll S; }; queue<heapnode> q; void addedge(int from,int to,int c,int p,int r){ a[++num].to=to,a[num].p=p,a[num].r=r,a[num].c=c; a[num].next=a[from].first; a[from].first=num; } void spfa(){ memset(dp,127/3,sizeof(dp));inf=dp[0][0]; memset(have,0,sizeof(have)); dp[1][1]=0;q.push((heapnode){1,1});have[1][1]=1; while(!q.empty()){ int now=q.front().id; ll s=q.front().S; have[now][s]=0; q.pop(); for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(s&(1<<(a[i].c-1))){ if(dp[to][s|(1<<(to-1))]>dp[now][s]+a[i].p){ dp[to][s|(1<<(to-1))]=dp[now][s]+a[i].p; if(!have[to][s|(1<<(to-1))]) { have[to][s|(1<<(to-1))]=1; q.push((heapnode){to,s|(1<<(to-1))}); } } } else{ if(dp[to][s|(1<<(to-1))]>dp[now][s]+a[i].r){ dp[to][s|(1<<(to-1))]=dp[now][s]+a[i].r; if(!have[to][s|(1<<(to-1))]){ have[to][s|(1<<(to-1))]=1; q.push((heapnode){to,s|(1<<(to-1))}); } } } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y,c,p,r;scanf("%d%d%d%d%d",&x,&y,&c,&p,&r); addedge(x,y,c,p,r); } spfa(); int ans=inf; for(int i=0;i<=(1<<n)-1;i++){ ans=min(ans,dp[n][i]); } if(ans==inf)cout<<"impossible"; else cout<<ans; return 0; }