hdu4281 状态压缩~MTSP最优值

一开始很简单的以为跟之前写的一样,多加个就可以了,第一问确实没问题,第二问就错的离谱了敲打,看了网上的解题思路,果断自己写了一个,代码写得比较搓委屈,不过时间复杂度还可以大笑


ACcode:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>

const int NS=15;
const int INF=1<<30;

struct Point
{
    int x,y,c;
} p[NS+1];

int top,flag,lim;
int u,v,t,w,n,m;
int state[1<<NS],tim[1<<NS][NS];
int p2[NS+2],bit[1<<NS][NS];
int dp[1<<NS],r[1<<NS],g[NS+1][NS+1];

int Dist(Point a,Point b)
{
    return ceil( sqrt( 1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y) ) );
}

void prepare()
{
    p2[0]=1;
    for (int i=1; i<NS; i++)
    p2[i]=p2[i-1]<<1;

    lim=1<<NS;
    for (int t,i=0; i<lim; i++)
    {
        t=0;
        for (int j=0; j<NS; j++)
        if (p2[j]&i) bit[i][++t]=j;
        bit[i][0]=t;
    }
}

int Min(int a,int b)
{
    return a<b?a:b;
}

int dp1()
{
    int u,v,w,t;
    for (int i=0; i<lim; i++)
    dp[i]=INF,r[i]=INF;
    dp[0]=1,r[0]=0;
    for (int i=1; i<lim; i++)
    for (int j=1; j<=bit[i][0]; j++)
    {
            u=bit[i][j],v=i-p2[u],w=r[v]+p[u].c;
            if (w<=m)
            {
                if (dp[i]>dp[v])
                dp[i]=dp[v],r[i]=w;
                else if (dp[i]==dp[v])
                r[i]=Min(w,r[i]);
            }
            if (p[u].c<=m)
            {
                if (dp[i]>(dp[v]+1.0))
                dp[i]=dp[v]+1,r[i]=p[u].c;
                else if (dp[i]==dp[v]+1)
                r[i]=Min(p[u].c,r[i]);
            }
    }
    return dp[lim-1]>=INF?-1.0:dp[lim-1];
}

void init()
{
    top=0;
    memset(state,0,sizeof(state));
    for (int s,t,i=0;i<lim;i++)
    {
        s=0;
        for (int j=1;j<=bit[i][0];j++)
        t=bit[i][j],s+=p[t].c;
        if (s<=m) state[i]=1;
    }
}

int dp2()
{
    init();
    for (int i=0;i<lim;i++)
    for (int j=0;j<n;j++)
    tim[i][j]=INF;
    for (int i=0;i<lim;i++)
    dp[i]=INF;
    dp[0]=0;
    for (int i=0;i<n;i++)
    if (p[i].c<=m)
    tim[p2[i]][i]=g[n][i];

    for (int i=0;i<lim;i++)
    if (state[i])
    for (int j=1;j<=bit[i][0];j++)
    {
        u=bit[i][j],v=i-p2[u];
        for (int k=1;k<=bit[v][0];k++)
        t=bit[v][k],
        tim[i][u]=Min(tim[i][u],tim[v][t]+g[t][u]);
        dp[i]=Min(dp[i],tim[i][u]+g[u][n]);
    }
    for (int i=1;i<lim;i++)
    {
        for (int j=n;j>=0;j--)
        if (p2[j]&i){ t=p2[j];break; }
        for (int j=i;j!=t;j=i&(j-1))
        dp[i]=Min(dp[i],dp[j]+dp[i^j]);
        dp[i]=Min(dp[i],dp[t]+dp[i^t]);
    }
    return dp[lim-1]>=INF?-1:dp[lim-1];
}

int main()
{
    prepare();
    while (~scanf("%d %d",&n,&m))
    {
        n--,flag=0,lim=1<<n;

        scanf("%d%d",&p[n].x,&p[n].y);
        for (int i=0; i<n; i++)
        scanf("%d%d",&p[i].x,&p[i].y);
        scanf("%d",&p[n].c);
        for (int i=0; i<n; i++)
        scanf("%d",&p[i].c),
        flag+= p[i].c>m?1:0;

        if (flag)
        {
            printf("-1 -1\n");
            continue;
        }
        for (int i=0; i<=n; i++)
        for (int j=i+1; j<=n; j++)
        g[i][j]=g[j][i]= i==j?0:Dist(p[i],p[j]);

        printf("%d %d\n",dp1(),dp2());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值