糯米

TI DaVinci, gstreamer, ffmpeg
随笔 - 167, 文章 - 0, 评论 - 47, 引用 - 0
数据加载中……

POJ 3123 Ticket to Ride 动态规划+Minimal Steiner Tree

这题绝对不是盖的。
题目大意是:
给出一个无向图,和四对数据。每对数据分别为图中的两个点。
要求添加一些边,使每对点都能连通,让总边权最小。

首先考虑一个子问题:指定一些点,添加一些边,让它们连通,并且总边权最小。
这个问题就是Minimal Steiner Tree问题,解决方法可以见这里
这问题不是盖的,它居然是NP完全问题。。
汗。。今天终于在POJ见识到啥叫NP完全问题了。。

大的问题可以分为多个子问题。可以枚举所有pair的连接状况。
比如说 {1和2链接,3和4链接} 或者 {1独立,2独立,3和4链接} 等等
一共有15种情况。分别为
    // 1,1,1,1
    {{1},{2},{3},{4}},
    // 1,1,2
    {{1,2},{3},{4}},
    {{1,3},{2},{4}},
    {{1,4},{2},{3}},
    {{2,3},{1},{4}},
    {{2,4},{1},{3}},
    {{3,4},{1},{2}},
    // 2,2
    {{1,2},{3,4}},
    {{1,3},{2,4}},
    {{1,4},{2,3}},
    // 1,3
    {{1,2,3},{4}},
    {{1,2,4},{3}},
    {{1,3,4},{2}},
    {{2,3,4},{1}},
    // 4
    {{1,2,3,4}},

其中有一些是重复的,就可以开一个数组保存下来。
贴一个我的程序。当然,这个是TLE的。。官方的数据需要将近一分钟才能跑完。
另外一个标程运行飞快,用得是更好的方法,点这里


#include <stdio.h>
#include 
<string.h>
#include 
<algorithm>
#include 
<cmath>

using namespace std;

char names[32][32];
int N, M;
int W[32][32];
const int INF = 10032*32;
int pairs[4];
int dp[256][2], dn;

int getcity(char *s)
{
    
int i;
    
for (i = 0; i < N; i++)
        
if (!strcmp(s, names[i]))
            
break;
    
return i;
}

int prim(int mask)
{
    
int i, j, mc, mi, a, c, t;

    c 
= 0;
    
for (i = 0; i < N; i++
        
if (mask & (1 << i)) {
            a 
= 1 << i;
            c
++;
        }

    t 
= 0;
    
while (--c) {
        mc 
= INF;
        
for (i = 0; i < N; i++)
            
if (a & (1 << i)) 
                
for (j = 0; j < N; j++)
                    
if (((mask ^ a) & (1 << j)) && W[i][j] < mc) {
                        mc 
= W[i][j];
                        mi 
= j;
                    }
        
if (mc == INF)
            
return INF;
        a 
|= 1 << mi;
        t 
+= mc;
    }

    
return t;
}

int K;

int dfs(int start, int mask, int n)
{
    
int i, r;

    
if (n >= K - 2)
        
return prim(mask);
    
    r 
= prim(mask);
    
for (i = start; i < N; i++
        
if ((1 << i) & ~mask) 
            r 
= min(r, dfs(i+1, mask|(1<<i), n+1));

    
return r;
}

int minicost(int mask)
{
    
int i, r;

    
for (i = 0; i < dn; i++)
        
if (mask == dp[i][0])
            
return dp[i][1];

    K 
= 0;
    
for (i = 0; i < N; i++)
        
if (mask & (1 << i))
            K
++;
    
    r 
= dfs(0, mask, 0);

    dp[dn][
0= mask;
    dp[dn][
1= r;
    dn
++;
    
return r;
}

int stats[15][8][8= {
    
// 1,1,1,1
    {{1},{2},{3},{4}},
    
// 1,1,2
    {{1,2},{3},{4}},
    {{
1,3},{2},{4}},
    {{
1,4},{2},{3}},
    {{
2,3},{1},{4}},
    {{
2,4},{1},{3}},
    {{
3,4},{1},{2}},
    
// 2,2
    {{1,2},{3,4}},
    {{
1,3},{2,4}},
    {{
1,4},{2,3}},
    
// 1,3
    {{1,2,3},{4}},
    {{
1,2,4},{3}},
    {{
1,3,4},{2}},
    {{
2,3,4},{1}},
    
// 4
    {{1,2,3,4}},
};

int main()
{
    
int i, j, k, a, b, c, ans;
    
char sa[32], sb[32];

    
while (scanf("%d%d"&N, &M), N) {
        
for (i = 0; i < N; i++)
            scanf(
"%s", names[i]);
        
for (i = 0; i < N; i++)
            
for (j = 0; j < N; j++)
                W[i][j] 
= INF;
        
for (i = 0; i < M; i++) {
            scanf(
"%s%s%d", sa, sb, &c);
            a 
= getcity(sa);
            b 
= getcity(sb);
            W[a][b] 
= W[b][a] = min(W[a][b], c);
        }
        
for (i = 0; i < 4; i++) {
            scanf(
"%s%s", sa, sb);
            a 
= getcity(sa);
            b 
= getcity(sb);
            pairs[i] 
= (1 << a) | (1 << b);
        }

        
// floyd
        for (k = 0; k < N; k++)
            
for (i = 0; i < N; i++)
                
for (j = 0; j < N; j++)
                    W[i][j] 
= min(W[i][k] + W[k][j], W[i][j]);

        dn 
= 0;
        ans 
= INF;
        
for (i = 0; i < 15; i++) {
            c 
= 0;
            
for (j = 0; stats[i][j][0]; j++) {
                a 
= 0;
                
for (k = 0; stats[i][j][k]; k++)
                    a 
|= pairs[stats[i][j][k] - 1];
                c 
+= minicost(a);
            }
            ans 
= min(ans, c);
        }

        printf(
"%d\n", ans);
    }
    
return 0;
}



 

posted on 2011-02-24 00:44 糯米 阅读(1082) 评论(0)  编辑 收藏 引用 所属分类: POJ


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理