• P1171 售货员的难题 喻队状压 DP


    题目描述

    某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。

    输入输出格式

    输入格式:

    村庄数n和各村之间的路程(均是整数)。

    输出格式:

    最短的路程。

    输入输出样例

    输入样例#1:
    3
    0 2 1
    1 0 2
    2 1 0
    输出样例#1:
    3

    说明

    输入解释

    3 {村庄数}

    0 2 1 {村庄1到各村的路程}

    1 0 2 {村庄2到各村的路程}

    2 1 0 {村庄3到各村的路程}


    差不多是我第一次做状压题,参考了洛谷的题解(明明就是一样的),总的来说差不多理解了状压。

    状压的状态转移是由位运算来优化实现的,一般用两个位运算:

    get : 用来确定某一位是否走过(define最快)

    #define get(a , b) ((a >> b-1) & 1)

    replace:用来得到之前的状态(依旧是define)

    #define replace(a , b) (a ^ (1 << b-1))

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    #define il inline
    #define db double
    #define replace(a , b) (a ^ (1 << b-1))
    #define get(a , b) ((a >> b-1) & 1)
    #define min(a , b) ((a) < (b) ? (a) : (b))
    using namespace std;
    il int gi()
    {
        int x=0,y=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
            {
                if(ch=='-')
                    y=-1;
                ch=getchar();
            }
        while(ch>='0'&&ch<='9')
            {
                x=x*10+ch-'0';
                ch=getchar();
            }
        return x*y;
    }
    int n,m,f[1<<21][21],r[21][21],ans=2e9,s;
    int main()
    {
        n=gi();
        m=(1<<n)-1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                r[i][j]=gi();
        for(int i=1;i<=m;i+=2)
            for(int j=1;j<=n;j++)
                f[i][j]=2e9;
        f[1][1]=0;
        for(int i=3,k=2,p=4;i<=m;i+=2)
            {
                if(i>p)
                    p=p<<1,k++;
                for(int j=2;j<=k;j++)
                    {
                        if(get(i,j))
                            {
                                s=replace(i,j);
                                for(int l=1;l<j;l++)
                                    f[i][j]=min(f[i][j],f[s][l]+r[l][j]);
                                for(int l=j+1;l<=k;l++)
                                    f[i][j]=min(f[i][j],f[s][l]+r[l][j]);
                            }
                    }
            }
        for(int i=2;i<=n;i++)
            ans=min(ans,f[m][i]+r[i][1]);
        printf("%d
    ",ans);
        return 0;
    }
    PEACE
  • 相关阅读:
    自己写的asp日历控件
    处处留心皆学问
    模块化闲谈
    原理……
    DIV和SPAN的区别
    javascript学习感触
    CSS 匹配顺序
    配置闲谈
    找到的一个读取shape数据的代码
    问题和收获
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7455155.html
Copyright © 2020-2023  润新知