地址:http://poj.org/problem?id=3411
题意:给了N个城市,给出若干路径,可从a到b,若之前经过过c城市则收费p,否则收费r,计算从1到n城市的路费最小值。
思路:
1 . 状态压缩DP。用dp [ i ] [ j ] 表示在i状态下到达j城市的最小收费,其中i用二进制形式表示所有城市的访问情况。
2 . 动态规划的方法类似spfa算法,从dp [ 1 ] [ 1 ] 开始对它能影响到的城市的各种情况进行松弛(若到达N城市显然没有必要入队再计算),显然最后的结果是存储在dp [ x ] [ n ] (0<x<( 1<<n ))中的最小值。
PS:
居然写代码的时候把p,r写反了,这英语啊~~~~
还有,记得n=1的特殊情况,部分代码可能会出现n=1的情况下cout<<"impossile"的问题,比如说,我。。。
最后吐槽下,明明是状态压缩DP,为什么分类在中级搜索里,理解不能啊!!!
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define MAX 1000000000
int dp[(1<<10)][11];
int cost,n,m;
struct node{
int i,j;
};
struct edge{
int b,c,p,r;
};
vector<edge> e[11];
void spfa(){
int i,j,k,vis,a,b,c,p,r;
dp[1][1]=0;
node t;
t.i=1;
t.j=1;
queue<node> q;
q.push(t);
while(!q.empty()){
node fm=q.front();
q.pop();
vis=fm.i;
a=fm.j;
for(k=0;k<e[a].size();k++){
b=e[a][k].b;
c=e[a][k].c;
p=e[a][k].p;
r=e[a][k].r;
int new_cost = (vis&(1<<(c-1)) ? p :r ) ;
new_cost+=dp[vis][a];
int new_vis = vis;
if((vis&(1<<(b-1)))==0) new_vis+=(1<<(b-1));
if(new_cost<dp[new_vis][b]){
t.i=new_vis;
t.j=b;
dp[new_vis][b]=new_cost;
if(b!=n){
q.push(t);
}
else{
if(cost>dp[new_vis][n])
cost=dp[new_vis][n];
}
}
}
}
return ;
}
int main(){
int i,j;
while(cin>>n>>m){
for(i=1;i<11;i++)
e[i].clear();
for(i=0;i<(1<<10);i++)
for(j=0;j<11;j++){
dp[i][j]=MAX;
}
cost=MAX;
for(i=0;i<m;i++){
int a;
edge k;
cin>>a>>k.b>>k.c>>k.p>>k.r;
e[a].push_back(k);
}
spfa();
if(n==1) cost=0;
if(cost==MAX)
cout<<"impossible"<<endl;
else
cout<<cost<<endl;
}
return 0;
}