• HDU3001 Traveling (状压dp+三进制+Tsp问题总结)


    (1)这道题最多可以走两次,所以有0, 1, 2三种状态,所以我们要用三进制

    如果要用三进制,就要自己初始化两个数组, 一个是3的n次方,一个是三进制数的第几位的数字是什么

    void init()
    {
    	three[0] = 1;
    	REP(i, 1, 11)
    		three[i] = three[i-1] * 3;
    	REP(i, 0, three[10])
    	{
    		int t = i;
    		REP(j, 0, 10)
    		{
    			digit[i][j] = t % 3;
    			t /= 3;
    			if(t == 0) break;
    		}
    	}
    }

    同时这里不能用位运算,因为不是二进制。如果涉及到某一位加1,就加上就好了,不能用|

    然后统计答案的时候比较麻烦,要枚举每一位是不是0

    (2)凡是涉及到进制的,下标都从0开始。输入的时候记得要下标减减

    (3)Tsp问题的基本套路是这样的(我用的是填表法)

    dp数组全部初始化为最大值

    起点初始化为0,即dp[1 << i][i] = 0

    第一层循环枚举所有可能的状态S

    第二层枚举当前点i,这里要求这个点已经经过

    第二层枚举之前的点j,这里同样要求这个点已经经过

    dp[state][i] = min(dp[state][i], dp[state^(1 << i)][j] + dist[j][i])

    记住要去掉当前这个点

    最后答案就是min(dp[(1 << n) - 1][i])

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define REP(i, a, b) for(int i = (a); i < (b); i++) 
    #define _for(i, a, b) for(int i = (a); i <= (b); i++) 
    using namespace std;
    
    const int MAXN = 15;
    int dist[MAXN][MAXN], dp[60000][MAXN], n, m;
    int three[MAXN], digit[60000][MAXN];
    
    void init()
    {
    	three[0] = 1;
    	REP(i, 1, 11)
    		three[i] = three[i-1] * 3;
    	REP(i, 0, three[10])
    	{
    		int t = i;
    		REP(j, 0, 10)
    		{
    			digit[i][j] = t % 3;
    			t /= 3;
    			if(t == 0) break;
    		}
    	}
    }
    
    int main()
    {
    	init();
    	while(~scanf("%d%d", &n, &m))
    	{
    		memset(dist, 0x3f, sizeof(dist));
    		while(m--)
    		{
    			int u, v, w;
    			scanf("%d%d%d", &u, &v, &w); u--; v--; //注意要-- 
    			dist[u][v] = dist[v][u] = min(dist[u][v], w);
    		}
    		
    		int ans = 1e9;
    		memset(dp, 0x3f, sizeof(dp)); //初始化不能忘 
    		REP(i, 0, n) dp[three[i]][i] = 0;
    		
    		REP(S, 0, three[n])
    		{
    			bool ok = true;
    			REP(i, 0, n)
    			{
    				if(digit[S][i] == 0) { ok = false; continue; } //i要已经经过。 
    				REP(j, 0, n) if(digit[S][j] >= 1) //j已经经过 
    					dp[S][i] = min(dp[S][i], dp[S-three[i]][j] + dist[j][i]);
    			} 	
    			if(ok) 
    				REP(i, 0, n) 
    					ans = min(ans, dp[S][i]);
    		}
    		printf("%d
    ", ans == 1e9 ? -1 : ans);
    	}
    		
    	return 0;
    }
  • 相关阅读:
    壶公随感
    消息称微软受谷歌刺激 急于收购雅虎(zz)
    远程注销Windows用户
    "杀人"游戏中的一些规律
    由两点的经纬度估算距离
    我的城市?
    Blog里的一个bug,dudu看能否修正?
    这两天真烦
    发简历,找上海.Net方面软件开发工作
    "上海.NET俱乐部"聚会筹备进展
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819327.html
Copyright © 2020-2023  润新知