百练4124:海贼王之伟大航路

题意: 该题用到了状态压缩动态规划,时间复杂度是O(2^n)*(n^2),因为n数量较少所以可以用这种方法,
   其中需要注意的是前n的二进制数表示是2的n此方减1,
解题思想:dp[i][j] 就是表示j属于i这个集合里的数,表示的是以j为结尾时的最小值,就是遍历以i集合内的数为结尾的值求最小值,
    然后再考虑影响当前状态的条件,依次递推


#include<bits/stdc++.h>

using namespace std;

const int maxn=(1<<16)+1;
const int m=16+1;
int dp[maxn][m];
int p[m][m];

int main()
{
    int i,j,k,n,_j,_k;
    while(scanf("%d",&n)==1)
    {
        for(i=1; i<=n; ++i)
        {
            for(j=1; j<=n; ++j)
            {
                scanf("%d",&p[i][j]);
            }
        }
        memset(dp,0x7f,sizeof(dp));
        dp[1][1]=0; //这个先决条件不可以少
        int ans=1<<n;
        for(i=1; i<ans; ++i) // 当n=2时 ans 二进制数为11当n = 3时 ans =  二进制数111,所以最终输出为dp[ans-1][n]
        {
            for(j=1,_j=1; j<=n; ++j,_j<<=1)
            {
                if(i&_j)    //岛屿j在去过的岛屿i中
                {
                    for(k=1,_k=1; k<=n; _k<<=1,++k)
                    {
                        if(k!=j&&(i&_k))
                        {
                            dp[i][j]=min(dp[i][j],dp[i-_j][k]+p[k][j]);
                        }
                    }//如k = 7时对应的二进制数为111。dp[7(111)][2] = min(dp[7(111)][2],dp[5(101)][j]+G[j][i])。
                    //在求dp[7][x]用到了dp[5][x](x无实意),因为是从小到大开始遍历,所以此时dp[5][x]已经求出
                }
            }
        }
        printf("%d\n",dp[ans-1][n]);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值