• uva 10944 Nuts for nuts..(状压dp)


    题意:一幅地图中给出松鼠起点,各坚果的信息,求松鼠收集所有坚果并返回起点的最小步数;

    思路:

         用二进制数表示坚果的收集状态,0表示未收集,1已收集;mm[i][j]表示节点i和j的相对距离;f[i][j]表示在收集状态为j是收集i的最小步数;

         显然,收集每颗坚果的最小步数为f[i][2的(i-1)次方]=mm[0][i];

         递增枚举状态值i,状态i中最后被收集的坚果j,枚举i外的坚果k。

         f[k][i+1<<(k-1)]=min( f[k][i+1<<(k-1)],f[j][i]+mm[j][k]);

        所有坚果收集后,若最后一颗为i,则到i的最小步数为f[i][1<<(n)-1],加上返回起点的步数map[0][i],找到最少步数;

       ans=min(f[i][1<<(n)-1]+mm[0][i]);(枚举i)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf (1<<20)
    #define N 30
    #define M 65536
    using namespace std;
    int f[N][M];
    char s[N];
    int mm[N][N];
    int x[N],y[N];
    int num,n,m,ans,maxz;
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            num=0;
            for(int i=0;i<n;i++)
            {
                scanf("%s",s);
                for(int j=0;j<m;j++)
                {
                    if(s[j]=='#'){
                        x[++num]=i;
                        y[num]=j;//坚果位置
                    }
                    else if(s[j]=='L'){
                        x[0]=i;y[0]=j;//当前位置
                    }
                }
            }
            if(!num){
                printf("0
    ");continue;
            }
            for(int i=0;i<=num;i++)
                for(int j=0;j<=num;j++)
                mm[i][j]=max(abs(x[i]-x[j]),abs(y[i]-y[j]));//计算节点间相对距离的矩阵
            maxz=(1<<num)-1;
            for(int i=0;i<=maxz;i++){
                for(int j=0;j<=num;j++)
                    f[j][i]=inf;
            }
            for(int i=1;i<=num;i++) f[i][1<<(i-1)]=mm[0][i];//只收集第i个坚果的步数
            for(int i=0;i<maxz;i++)  //枚举当前坚果被收集的状态
            {
                for(int j=1;j<=num;j++) if(i&(1<<(j-1)))//枚举最后被收集的坚果j
                    for(int k=1;k<=num;k++)  //枚举i状态外的坚果k,调整k被收集的最优步数
                    if(!(i&(1<<(k-1)))) f[k][i+(1<<(k-1))]=min(f[k][i+(1<<(k-1))],f[j][i]+mm[j][k]);
            }
            ans=inf;
            for(int i=1;i<=num;i++)  //枚举最后被收集的坚果(返回‘L’位置的最少步数)i,调整最优步数
                ans=min(ans,f[i][maxz]+mm[i][0]);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    [HDU3094]A tree game
    专题总结(博弈论)
    [ZJOI2009]染色游戏
    [AtCoder3954]Painting Machines
    异或
    种树
    [PA2014]Fiolki
    简单题
    2、JUC--CAS算法
    1、JUC--volatile 关键字-内存可见性
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4574478.html
Copyright © 2020-2023  润新知