• [题解]传递游戏


    题目来源:无

    激动,第一次写状压dp

    题目描述

    毛大神最近在玩一个传递游戏,即有N个人在做传递物品的游戏,这N个人的编号为1,2,3...N-1,N。游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位;下一个人可以传递给未接过物品的任意一人。

    即物品只能经过同一个人一次,而且每次传递过程都有一个代价;不同的人传给不同的人的代价值之间没有联系。

    毛大神想知道当物品经过所有N个人后,整个过程的最小的代价总和是多少。

    输入输出格式

    输入格式:

    第一行为N,表示共有N个人;

    以下为N×N的矩阵,第i行第j列的数为A[i][j],表示物品从编号为i的人传递到编号为j的人所花费的代价,其中A[i][i]=-1(因为物品不能自己传给自己)。

    输出格式:

    共一行,一个数,为最小的代价总和。

    输入输出样例

    输入样例:

    2
    1 9794
    2724 -1

    输出样例:

    2724

    说明

    数据规模:

    对于50%的数据,1≤N≤11;

    对于100%的数据,1≤N≤16;1≤A[i][j]≤10000;A[i][i]=-1。

    题目分析

    分析

    经过个人的作死尝试,直接 DFS 最高50分,我们需要优化,题目要求节点不重复,又是一个有向图(无向图 最小生成树 秒切),我们可以用 状压dp 优化,何为 状压dp ?就是将某种状态用二进制表示 如 10110 可能就是选择了1、3、4位置的情况,当然这是一个基础的裸状压dp,我们枚举以 i 结尾的状态,得出下一个状态的代价。

    代码

     1 #include<iostream>
     2 #include<fstream>
     3 #define lowbit(l) (l&(-l)) 
     4 using namespace std;
     5 
     6 const int Max_N=17;
     7 const int Inf=((1<<31)-1)>>1;
     8 
     9 int n;
    10 int loc1[1<<16];
    11 int A[Max_N][Max_N],dp[Max_N][1<<16];
    12 
    13 int main()
    14 {    
    15     scanf("%d",&n);
    16     int i,j,l,k,t;
    17     for(i=1;i<=n;i++)
    18         for(j=1;j<=n;j++)
    19             scanf("%d",&A[i][j]);
    20     for(i=1;i<=n;i++)
    21         for(j=1;j<=(1<<n)-1;j++)
    22             dp[i][j]=Inf;
    23 //    memset         
    24     for(i=1,j=1;i<=1<<(n-1);i<<=1,j++)
    25         loc1[i]=j;
    26     for(l=1;l<=(1<<n)-1;l++){
    27         if(l==lowbit(l)){
    28             int p=loc1[l];
    29             for(i=1,j=1;i<=1<<(n-1);i<<=1,j++)
    30                 if(j^p)
    31                     dp[j][l|i]=min(dp[j][l|i],A[p][j]);
    32         }
    33         else{
    34             for(k=1,t=1;k<=1<<(n-1);k<<=1,t++)
    35                 if(l&k)
    36                     for(i=1,j=1;i<=1<<(n-1);i<<=1,j++)
    37                         if(!(l&i))
    38                             dp[j][l|i]=min(dp[j][l|i],dp[t][l]+A[t][j]);
    39         }
    40     }
    41     int res=Inf;
    42     for(i=1;i<=n;i++)
    43         res=min(res,dp[i][(1<<n)-1]);
    44     printf("%d",res);
    45     return 0;
    46 }
    View Code

    写在最后的话:

    题解仅供思路,要想成为 dalao ,请学会并尽量会做到教他人甚至自己写题解。

    博主(目前)是一名初二蒟蒻,如有问题还请大家指出,一起交流学习!

    Happy every day!        ——2019.4.11

  • 相关阅读:
    步步为营 .NET 设计模式学习笔记 四、Singleton(单例模式)
    步步为营 .NET 设计模式学习笔记 九、Command(命令模式)
    步步为营 .NET 设计模式学习笔记 十八、Template(模板模式)
    步步为营 .NET 代码重构学习笔记 七
    步步为营 .NET 设计模式学习笔记 十九、Chain of Responsibility(职责链模式)
    步步为营 .NET 设计模式学习笔记 二十二、Memento(备望录模式)
    步步为营 .NET 设计模式学习笔记 十四、Decorator(装饰模式)
    步步为营 .NET 代码重构学习 十一
    步步为营 .NET 设计模式学习笔记 一、开篇(设计模式之泡妞二十三招)
    步步为营 .NET 设计模式学习笔记 七、Proxy(代理模式)
  • 原文地址:https://www.cnblogs.com/lihepei/p/10795589.html
Copyright © 2020-2023  润新知