HDU-3768Shopping

来源:互联网 发布:c语言if多个语句嵌套 编辑:程序博客网 时间:2024/05/21 06:11

题目:http://acm.hdu.edu.cn/statistic.php?pid=3768

题意:给定无向图,问从0出发遍历所有指定点所需最短时间,点100000,边100000,指定点<=10

思路:首先求出所有指定点两两之间的最短路,包括0点,

1:直接10!枚举遍历顺序,求出最小值

#include<cstdio>#include<iostream>#include<cstring>#include<queue>#include<string>#include<algorithm>using namespace std;const int N=100010;const int M=100010*2+10;const int INF=1000000000;struct Edge{    int to,next,dis;    Edge(){}    Edge(int To,int Next,int Dis)    {        to=To,next=Next ,dis=Dis;    }}e[M];int head[N];struct Spfa{    int total;    int low[N];    int vis[N];    void init()    {        total=0;        memset(head,-1,sizeof(head));    }    void add_edges(int from,int to,int dis)    {        e[total]=Edge(to,head[from],dis);        head[from]=total++;    }    void _spfa(int s)    {        memset(low,-1,sizeof(low));        low[s]=0;        memset(vis,0,sizeof(vis));        vis[s]=1;        queue<int> qq;        qq.push(s);        while(!qq.empty())        {            int u=qq.front();qq.pop();            vis[u]=0;            for(int i=head[u];i!=-1;i=e[i].next)            {                int v=e[i].to;                if(low[v]==-1||(low[v]>low[u]+e[i].dis))                {                    low[v]=low[u]+e[i].dis;                    if(!vis[v])                    {                        vis[v]=1;                        qq.push(v);                    }                }            }        }    }}spfa;int map[11][11];int store[11];int dp[(1<<10)][11];int s[20];void init(){    s[0]=1;    for(int i=1;i<20;i++)    {        s[i]=s[i-1]*2;    }}int main(){    int T;scanf("%d",&T);    while(T--)    {        init();        int n,m;scanf("%d%d",&n,&m);        spfa.init();        for(int i=0;i<m;i++)        {            int a,b,c;scanf("%d%d%d",&a,&b,&c);            spfa.add_edges(a,b,c);spfa.add_edges(b,a,c);        }        int ss;scanf("%d",&ss);        for(int i=0;i<ss;i++)        {            scanf("%d",&store[i]);        }        sort(store,store+ss);        int cnt=1;        for(int i=1;i<ss;i++)        {            if(store[i]!=store[i-1])store[cnt++]=store[i];        }        for(int i=0;i<cnt;i++)        {            spfa._spfa(store[i]);            map[i][i]=0;            for(int j=0;j<i;j++)            {                int ans=spfa.low[store[j]];                map[i][j]=map[j][i]=ans;            }        }        spfa._spfa(0);        map[cnt][cnt]=0;        for(int i=0;i<cnt;i++)        {            map[i][cnt]=map[cnt][i]=spfa.low[store[i]];        }        int nn=1<<cnt;        for(int i=0;i<nn;i++)        {            for(int j=0;j<=cnt;j++)dp[i][j]=INF;        }        dp[0][cnt]=0;s[cnt]=0;        for(int i=0;i<nn;i++)        {            for(int j=cnt;j>=0;j--)if(dp[i][j]<INF)            {                for(int k=0;k<=cnt;k++)                {                    if((i&s[k])==0)                    {                        dp[i|s[k]][k]=min(dp[i|s[k]][k],dp[i][j]+map[j][k]);                    }                }            }        }        /*int ans=INF;        for(int i=0;i<cnt;i++)        {            int bns=dp[nn-1][i]+map[i][cnt];            if(ans>bns)ans=bns;        }        printf("%d\n",ans);*/        printf("%d\n",dp[nn-1][cnt]);    }    return 0;}

2:状压dp[i][j];已经到过点集i,目前所在位置为j,所需要的时间

对于每个状态dp[i][j],枚举从j下一步要到达的地点k,

dp[  i|s[k]  ]=min(dp[ i|s[k] ],dp[i][j]+dis[j][k];


0 0
原创粉丝点击