zoukankan      html  css  js  c++  java
  • P1171

    经典的状压dp问题

    题解思路

    看到数据范围(1≤ n ≤ 20)

    我们考虑对已经到达过的村庄进行(2)进制状压,用第一维表示。

    另外,我们需要知道自己当前处于已经到哪个点,所以将其表示在第二维。

    所以得出状态(f[j][i])

    接下来的题解叙述中,状态中起点位置我并没有设定,所以会出现邻接矩阵中(k)(i)加一得情况

    接下来状态转移方程就比较容易设计了

    [f[j][i] = minlbrace f[s][k] +a[k+1][i+1] ,s =j xor i ,kin s brace ]

    该方程表示当前集合为(j)且目前处于(i)点,由当集合为(s)且处于(k)点时外加上从(k)(i)距离递推而来.

    其中(a[k+1][i+1])表示从(k)点到(i)点.

    集合(s)为集合(j)除去(i)点,(k)为集合(s)中某一点

    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    #define INF 1<<30;
    
    const int minn=(1<<19)+5;
    
    int f[minn][25];
    int  a[23][23];
    
    signed main()
    {
    	int n;
    	
    	memset(f,0x3f,sizeof(f));
    	
    	ios_base::sync_with_stdio(false);
    	cout.tie(NULL);
    	cin.tie(NULL);
    	
    	cin>>n;
    	
    	for(int i=1;i<=n;i++)
    		for(int  j=1;j<=n;j++)
    	{
    		cin>>a[i][j];
    	}
    	
    	n--;
    	
    	for(int j=1 ;j <= (1<<n) - 1 ; j++ )
    	{
    
    		for(int  i=1 ;i<=n;i++)
    		{
    
    			if(((1<<i-1) & j) == 0) continue;
    			
    			if( (1<<i-1)  ==  j   ) 
    			{
    				
    				f[j][i] = a[1][i+1];
    
    				break;
    			}
    			
    			int  s= j ^ (1<<i-1);
    			
    			for(int  k=1;k<=n;k++)
    			{
    				if((1<<k-1 & s) == 0) continue;
    				
    				f[j][i] = min(f[j][i] , f[s][k] + a[k+1][i+1]);
    
    			}
    			
    		}
    		
    	}
    	
    	int  ans=INF;
    	
    	for(int i=1;i<=n;i++)
    	{
    		ans=min(ans,f[(1<<n)-1][i] + a[i+1][1]);
    
    	}
    	
    	cout<<ans;
    	
    }
    
    
  • 相关阅读:
    为什么需要防火墙?
    比较流行的前端框架
    java基础面试题
    单列模式
    简单而且好用的随机验证码
    java中的九大隐藏变量.
    搭建Disuz论坛社区
    BZOJ 1006 [HNOI2008]神奇的国度
    COJ 0252 HDNOIP201304阻断传染
    BZOJ 1005 [HNOI2008]明明的烦恼
  • 原文地址:https://www.cnblogs.com/-Iris-/p/13543269.html
Copyright © 2011-2022 走看看