hdu4640 && hdu4281

来源:互联网 发布:微分销源码 编辑:程序博客网 时间:2024/06/17 09:06

hdu4281是多旅行商问题,hdu4640是三个旅行商,这不太影响解法,主要差别在于hdu4640要求不仅仅是每个节点访问一次,而且要每个节点只能经过一次,这样求single[state][u]的时候就不能直接枚举下一个点了,而是要根据边枚举,且下一个到达的点必影响state。

hdu4281:

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#include<cmath>#include<numeric>#include<queue>using namespace std;const int inf=0x3fffffff;int path[20][20];double x[20],y[20];int n,m,c[20];int dp1[1<<20];int state[1<<20],tot;bool ok[1<<20];void pre(){    tot=0;    int i,j,sum;    memset(ok,false,sizeof(ok));    for(i=0;i<(1<<n);++i)    {        sum=0;        for(j=0;j<n;++j)        {            if(i&(1<<j))            {                sum+=c[j];            }        }        if(sum<=m)        {            ok[i]=true;            state[tot++]=i;        }    }}int solve1()     //checked{    int i,j;    for(i=0;i<(1<<n);++i)        dp1[i]=inf;    dp1[0]=0;    for(i=1;i<(1<<n);++i)    {        for(j=0;j<tot;++j)        {            if((i|state[j])==i)            {                dp1[i]=min(dp1[i],dp1[i-state[j]]+1);            }        }    }    return dp1[(1<<n)-1]==inf?-1:dp1[(1<<n)-1];}int single[1<<20][20],best[1<<20];int solve2(){    int i,j,k,u,v;    for(i=0;i<(1<<n);++i)    {        for(j=0;j<n;++j)            single[i][j]=inf;        best[i]=inf;    }    single[1][0]=0;    for(i=1;i<(1<<n);++i)    {        if(ok[i])        {            for(j=0;j<n;++j)            {                if(i&(1<<j))                {                    best[i]=min(best[i],single[i][j]+path[j][0]);                    for(k=0;k<n;++k)                    {                        if(ok[i|(1<<k)]&&((i&(1<<k))==0))                        {                            single[i|(1<<k)][k]=min(single[i|(1<<k)][k],single[i][j]+path[j][k]);                        }                    }                }            }        }    }    for(i=0;i<(1<<n);++i)    {        for(j=i&(i-1);j;j=((j-1)&i))        {            best[i]=min(best[i],best[j]+best[(i^j)|1]);            if(j==0)                break;        }    }    return best[(1<<n)-1];}int main(){    int i,j,k,ans1,ans2;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=0;i<n;++i)        {            scanf("%lf%lf",&x[i],&y[i]);        }        for(i=0;i<n;++i)        {            scanf("%d",&c[i]);        }        memset(path,0,sizeof(path));        for(i=0;i<n;++i)        {            for(j=i+1;j<n;++j)            {                path[i][j]=path[j][i]=ceil(sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2)));            }        }        for(k=0;k<n;++k)        {            for(i=0;i<n;++i)            {                for(j=0;j<n;++j)                {                    path[i][j]=min(path[i][j],path[i][k]+path[k][j]);                }            }        }        pre();        ans1=solve1();        if(ans1==-1)        {            printf("-1 -1\n");        }        else        {            ans2=solve2();            printf("%d %d\n",ans1,ans2);        }    }    return 0;}


hdu4640:

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;const int inf=0x3fffffff;const int maxn=20;int single[1<<maxn][20];int dp[2][1<<maxn];struct edge{    int to,w,next;}ee[maxn*maxn*2];int e[maxn],ecnt,n,m;void addedge(int u,int v,int c){    ee[ecnt].to=v;ee[ecnt].w=c;ee[ecnt].next=e[u];e[u]=ecnt++;    ee[ecnt].to=u;ee[ecnt].w=c;ee[ecnt].next=e[v];e[v]=ecnt++;}void bfs(){    int u,msk1,msk2,v,i,j;    for(msk1=0;msk1<(1<<n);++msk1)    {        for(u=0;u<n;++u)        {            single[msk1][u]=inf;        }    }    queue<int> q1,q2;    q1.push(1);q2.push(0);single[1][0]=0;    while(!q1.empty())    {        msk1=q1.front();q1.pop();        u=q2.front();q2.pop();        for(i=e[u];i!=-1;i=ee[i].next)        {            v=ee[i].to;            if(single[msk1|(1<<v)][v]>single[msk1][u]+ee[i].w)            {                single[msk1|(1<<v)][v]=single[msk1][u]+ee[i].w;                q1.push(msk1|(1<<v));q2.push(v);            }        }    }    for(msk1=2;msk1<(1<<n);++msk1)    {        dp[0][msk1>>1]=inf;        for(j=0;j<n;++j)        {            dp[0][msk1>>1]=min(dp[0][msk1>>1],single[msk1|1][j]);        }    }    dp[0][0]=0;}int main(){    int t,cas=0,i,j,u,v,c,ans,tar,k,msk1,msk2;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        memset(e,-1,sizeof(e));ecnt=0;        while(m--)        {            scanf("%d%d%d",&u,&v,&c);            u--;v--;            addedge(u,v,c);        }        tar=0;        scanf("%d",&k);        while(k--)        {            scanf("%d",&u);            u-=2;            tar|=(1<<u);        }        bfs();        n--;        for(msk1=0;msk1<(1<<n);msk1++)        {            dp[1][msk1]=inf;            for(msk2=msk1;;msk2=((msk2-1)&msk1))            {                if(dp[0][msk2]!=inf&&dp[0][msk1^msk2]!=inf)                {                    dp[1][msk1]=min(dp[1][msk1],max(dp[0][msk2],dp[0][msk1^msk2]));                }                if(msk2==0)                    break;            }        }        ans=inf;        for(msk1=0;msk1<(1<<n);msk1++)        {            if((msk1&tar)==tar)            {                for(msk2=msk1;;msk2=((msk2-1)&msk1))                {                    ans=min(ans,max(dp[0][msk2],dp[1][msk2^msk1]));                    if(msk2==0)                        break;                }            }        }        if(ans==inf)        {            printf("Case %d: -1\n",++cas);        }        else        {            printf("Case %d: %d\n",++cas,ans);        }    }    return 0;}


 

 

原创粉丝点击