UVA 1424 - Salesmen (基础dp)


题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4170


题意:

对于一个连通无向图,给定一个有n个节点的序列A,找到具有相同节点的序列B(保证联通),求出最小的两个序列的距离,

距离的求法:

dist(AB) = $\displaystyle \sum^{{n}}_{{i=1}}$d (aibi)

where

d (ab) = $\displaystyle \left\{\vphantom{ \begin{array}{cc} 0 & \mbox{if } a=b \\  1 & \mbox{otherwise} \end{array} }\right.$$\displaystyle \begin{array}{cc} 0 & \mbox{if } a=b \\  1 & \mbox{otherwise} \end{array}$


思路:

dp[i][j] 表示第i个位置上以数字j的结尾的距离

考虑两个状态之间的转换

对于节点k,若j,k 联通

若j == path[i]  那么dp[i][j] = dp[i - 1][k] 

否则, dp[i][j] = dp[i - 1][k] + 1



#include 
#include 
#include 
#include 
using namespace std;
#define maxn 110
#define inf 0x3f3f3f3f
int dp[220][220];
int path[220];
int map[maxn][maxn];

int val(int x){
    if(x < 0) return -x;
    return x;
}
int main()
{
    int T,n,n1,n2;
    while(~scanf("%d",&T)){
        while(T--){
            scanf("%d %d",&n1,&n2);

            for(int i = 0; i <= n1; i ++)
            for(int j = 0; j <= n1; j ++){
                if(i == j) map[i][j] = 0;
                else map[i][j] = -1;
            }

            int from,end;
            while(n2--){
                scanf("%d %d",&from,&end);
                map[from][end]  = 1;
                map[end][from]  = 1;
            }
            scanf("%d",&n);
            for(int i = 1; i <= n; i ++)
                scanf("%d",&path[i]);

            memset(dp,inf,sizeof(dp));

            for(int i = 1; i <= n1; i ++)
                dp[1][i] = 1;
            dp[1][path[1]] = 0;

            for(int i = 2; i <= n; i ++){
                for(int j = 1; j <= n1 ; j ++){
                    dp[i][j] = inf;
                    for(int k = 1; k <= n1; k ++){
                        if(map[j][k] != -1) {
                            if(j == path[i])
                                dp[i][j] = min(dp[i][j] , dp[i - 1][k]);
                            else
                                dp[i][j] = min(dp[i][j] , dp[i - 1][k] + 1);
                        }
                    }
                }
            }
            int ans = inf;
            for(int i = 1; i <= n1; i ++){
                if(ans > dp[n][i]) ans = dp[n][i];
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}


你可能感兴趣的:(算法练习)