【状压】 poj 3411 Paid Roads

版权声明:转载标注来源喔~ https://blog.csdn.net/iroy33/article/details/89944404

题意:m条路连接n个城市,道路收费,可以在ci城市付Pi钱通过ai到bi的路,或者在bi付Ri的钱,问从1到n最少需要花多少钱?

思考:如果没有在ci城市付Pi钱这一条件的话,可以以Ri为权值跑dijkstra。加上这一条件后,如果ci城市已经到达过了,就加上Pi,否则加上Ri

参考代码

emm,这道题不用状压开个数组也成的,不过状压是真的方便鸭

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct edge
{
    int v,c,p,r,next;       //分别代表目的城市,城市c,..如题
    edge(){}
    edge(int v,int c,int p,int r,int next):v(v),c(c),p(p),r(r),next(next){}
}e[15];
struct node
{
    int cost,u;             //s状态下到达u了的最小花费
    int s;
    node(){}
    node(int cost,int u,int s):cost(cost),u(u),s(s){}
    bool operator <(const node &rhs)const
    {
        return cost>rhs.cost;   //一开始写反了,太久没用忘记了,心情复杂
    }
};
int head[15];
int cnt=0;
int vis[15][1<<15];
int n,m;
typedef pair<int,int> pii;
void addedge(int u,int v,int c,int p,int r)
{
    e[cnt]=edge(v,c,p,r,head[u]);
    head[u]=cnt++;
}
void dijkstra()
{
    memset(num,0,sizeof(num));
    priority_queue<node>q;
    node s(0,1,1);
    q.push(s);
    node tmp;
    while(!q.empty())
    {
        tmp=q.top();
        q.pop();
        int u=tmp.u;
        if(u==n) break;
        if(vis[u][tmp.s]) continue;     //注意不是要求状态只入队一次。而是状态只能扩展一次
        vis[u][tmp.s]=1;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            node now=tmp;
            int v=e[i].v,c=e[i].c;
            now.s|=(1<<(v-1));
            if(tmp.s&(1<<(c-1))) now.cost+=e[i].p;
            else now.cost+=e[i].r;
            now.u=v;
            q.push(now);
        }
    }
    if(tmp.u!=n) cout<<"impossible"<<endl;
    else cout<<tmp.cost<<endl;

}
int main()
{

    memset(head,-1,sizeof(head));
    cin>>n>>m;
    for(int i=1;i<=m;++i)
    {
        int u,v,c,p,r;
        cin>>u>>v>>c>>p>>r;
        addedge(u,v,c,p,r);
    }
    dijkstra();
    return 0;
}

感觉只要搜索登峰造极,能解决大部分dp(记忆化搜索)、博弈论(sg函数)和搜索问题emm

参考博客

需要注意的是一个地方可以走多次,但是走环的话一定不是个好选择,被选次数大于n-1就一定出现环了

const int N=15;
const int INF=0x3f3f3f3f;
int n,m;
struct edge
{
    int v,c,p,r;
    edge(){}
    edge(int v,int c,int p,int r):v(v),c(c),p(p),r(r){}
};
vector<edge>g[N];
int vis[N];
int ans=INF;
void dfs(int u,int cost)
{
    if(u==n&&ans>cost)
    {
        ans=cost;
        return ;
    }
    for(int i=0;i<g[u].size();++i)
    {
        int v=g[u][i].v,c=g[u][i].c;
        if(vis[v]>n-1) continue;
        vis[v]++;
        if(vis[c]) dfs(v,cost+g[u][i].p);
        else dfs(v,cost+g[u][i].r);
        vis[v]--;           //回溯
    }
    return ;

}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;++i)
    {
        int u,v,c,p,r;
        cin>>u>>v>>c>>p>>r;
        g[u].push_back(edge(v,c,p,r));
    }
    dfs(1,0);
    if(ans==INF) cout<<"impossible"<<endl;
    else cout<<ans<<endl;
    return 0;

}

猜你喜欢

转载自blog.csdn.net/iroy33/article/details/89944404