[题解]传递游戏

题目来源:无

激动,第一次写状压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

转载于:https://www.cnblogs.com/lihepei/p/10795589.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值