UVA-1424-Salesmen(DP)

Traveling salesmen of . (the prestigious Korean internet company) report their current location
to the company on a regular basis. They also have to report their new location to the company if
they are moving to another location. The company keep each salesman’s working path on a map of his
working area and uses this path information for the planning of the next work of the salesman. The
map of a salesman’s working area is represented as a connected and undirected graph, where vertices
represent the possible locations of the salesman an edges correspond to the possible movements between
locations. Therefore the salesman’s working path can be denoted by a sequence of vertices in the graph.
Since each salesman reports his position regularly an he can stay at some place for a very long time,
the same vertices of the graph can appear consecutively in his working path. Let a salesman’s working
path be correct if two consecutive vertices correspond either the same vertex or two adjacent vertices
in the graph.
For example on the following graph representing the working
area of a salesman, a reported working path [1 2 2 6 5 5
5 7 4] is a correct path. But a reported working path [1 2 2
7 5 5 5 7 4] is not a correct path since there is no edge in the
graph between vertices 2 a 7. If we assume that the salesman
reports his location every time when he has to report his location
(but possibly incorrectly), then the correct path could
be [1 2 2 4 5 5 5 7 4], [1 2 4 7 5 5 5 7 4], or [1 2 2 6 5 5 5 7 4].
The length of a working path is the number of vertices
in the path. We define the distance between two paths A =
a1a2 … an and B = b1b2 … bn of the same length n as
dist(A, B) = ∑n
i=1
d(ai
, bi)
where
d(a, b) = {
0 if a = b
1 otherwise
Given a graph representing the working area of a salesman and a working path (possible not a
correct path), A, of a salesman, write a program to compute a correct working path, B, of the same
length where the distance dist(A, B) is minimized.
Input
The input consists of T test cases. The number of test cases (T) is given in the first line of the input.
The first line of each test case contains two integers n1, n2 (3 ≤ n1 ≤ 100, 2 ≤ n2 ≤ 4, 950) where n1 is
the number of vertices of the graph representing the working map of a salesman and n2 is the number
of edges in the graph. The input graph is a connected graph. Each vertex of the graph is numbered
from 1 to n1. In the following n2 lines, each line contains a pair of vertices which represent an edge of
the graph. The last line of each test case contains information on a working path of the salesman. The
first integer n (2 ≤ n ≤ 200) in the line is the length of the path and the following n integers represent
the sequence of vertices in the working path.
Output
Print one line for each test case. The line should contain the minimum distance of the input path to a
correct path of the same length.
Sample Input
2
7 9
1 2
2 3
2 4
2 6
3 4
4 5
5 6
7 4
7 5
9 1 2 2 7 5 5 5 7 4
7 9
1 2
2 3
2 4
2 6
3 4
4 5
5 6
7 4
7 5
9 1 2 2 6 5 5 5 7 4
Sample Output
1
0

题意:给定N个点M条边的无向图,再给定长度为len的序列,修改序列使得图中任意两个相邻的值要么相等,要么直接联通。求出最小修改次数。

思路:DP[i][j]代表序列中第i个数如果以j结尾的最小修改次数。
枚举顶点k,如果k和第i数相等或者k和j联通,则可以进行状态转移。进行状态转移时,如果j和序列中第i个数相等则DP[i][j]=min(DP[i][j],DP[i-1][j])否则DP[i][k]=min(DP[i][j],DP[i-1][k]+1)。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=105;
const int INF=0x3f3f3f3f;
bool map[maxn][maxn];
int DP[maxn*2][maxn];//第i个数以j结尾的最小修改次数
int num[maxn*2];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int N,M;
        scanf("%d%d",&N,&M);
        memset(map,false,sizeof(map));
        memset(DP,0x3f,sizeof(DP));
        while(M--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            map[u][v]=map[v][u]=true;
        }
        int len;
        scanf("%d",&len);
        for(int i=1; i<=len; i++)
            scanf("%d",&num[i]);
        for(int i=1; i<=N; i++)
            DP[0][i]=0;//第零个数最小修改次数均为零
        for(int i=1; i<=len; i++)//枚举第i个数
            for(int j=1; j<=N; j++)//以j结尾
                for(int k=1; k<=N; k++)//被k替换
                    if(j==k||map[k][j]==true)//顶点相同或者相连说明可以替换
                        j==num[i]?DP[i][j]=min(DP[i][j],DP[i-1][k]):DP[i][j]=min(DP[i][j],DP[i-1][k]+1);
        int result=INF;
        for(int i=1; i<=N; i++)
            result=min(result,DP[len][i]);
        printf("%d\n",result);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值