Salesmen - UVa 1424 dp(送给大家)

Traveling salesmen of nhn. (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 Aa1a2...an and B = b1b2...bn of the same length n as

dist(AB) = d (aibi)

where

d (ab) = 

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 distancedist(AB) is minimized.

Input

The program is to read the input from standard 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 (3n1100, 2n24, 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 (2n200) in the line is the length of the path and the following n integers represent the sequence of vertices in the working path.

Output

Your program is to write to standard 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

题意:找一个可以在图上前行的序列,使得其与给定序列相差的数字数量最小,输出这个最小的值。

思路:dp[i][j]表示已经匹配好前i个序列并且最后停在j点时的最小权值。

AC代码如下:

[cpp] view plaincopy

    1. #include<cstdio>
    2. #include<cstring>
    3. #include<vector>
    4. #include<algorithm>
    5. using namespace std;
    6. vector<int> vc[110];
    7. int val[210],len[110],dp[210][110],INF=1e9;
    8. int main()
    9. {
    10. int t,T,n,m,i,j,k,u,v,length,f,ans;
    11. scanf("%d",&T);
    12. for(t=1;t<=T;t++)
    13. {
    14. scanf("%d%d",&n,&m);
    15. for(i=1;i<=n;i++)
    16. vc[i].clear();
    17. for(i=1;i<=m;i++)
    18. {
    19. scanf("%d%d",&u,&v);
    20. vc[u].push_back(v);
    21. vc[v].push_back(u);
    22. }
    23. for(i=1;i<=n;i++)
    24. {
    25. vc[i].push_back(i);
    26. len[i]=vc[i].size();
    27. }
    28. scanf("%d",&length);
    29. for(i=1;i<=length;i++)
    30. scanf("%d",&val[i]);
    31. for(i=1;i<=n;i++)
    32. if(i==val[1])
    33. dp[1][i]=0;
    34. else
    35. dp[1][i]=1;
    36. for(i=2;i<=length;i++)
    37. {
    38. for(u=1;u<=n;u++)
    39. {
    40. dp[i][u]=INF;
    41. if(u==val[i])
    42. f=0;
    43. else
    44. f=1;
    45. for(k=0;k<len[u];k++)
    46. {
    47. v=vc[u][k];
    48. dp[i][u]=min(dp[i][u],dp[i-1][v]+f);
    49. }
    50. }
    51. }
    52. ans=INF;
    53. for(i=1;i<=n;i++)
    54. ans=min(ans,dp[length][i]);
    55. printf("%d\n",ans);
    56. }
    57. }
时间: 2025-01-15 05:16:46

Salesmen - UVa 1424 dp(送给大家)的相关文章

uva 1424 dp

UVA 1424 - Salesmen 给出一副图,并且给出nhn走过的路径记入,路径可能是错的,问最少修改几个地方可以使得路径是正确的. dp[i][j] 表示修改第i个位置为j点的前i个位置的最小修改次数. dp[i][j] = min(dp[i-1][k] + (j == a[i])); {w[k][j] == true 即存在路径k~j} 然后再最后一个点找一个最小值. #include <cstdio> #include <cstring> #include <io

递推DP UVA 1424 Salesmen

题目传送门 1 /* 2 题意:给定包含n个点的无向图和一个长度为L的序列,修改尽量少的点使得相邻的数字相同或连通 3 DP:状态转移方程:dp[i][j] = min (dp[i][j], dp[i-1][k] + (j != a[i])); 4 dp[i][j]表示前i个数字以j结尾的最小花费.我自己写了很长时间,很复杂,状态转移的不好. 5 应该能知道前一个状态的所有情况,每一维数组记录的就是一个状态 6 */ 7 /************************************

UVA 1424 二 Salesmen

Salesmen Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 1424 Traveling salesmen of nhn. (the prestigious Korean internet company) report their current location to the company on a regular basis. They

uva 1401 dp+Trie

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=4147 题意:给定一个字符串,以及若干单词,求有几种方式能用单词组成字符串 我先是dp方程推得有问题不知怎么修改搞得卡了很久,然后就是数组开得太小一直RE trie数组大小=单词个数*单词长度  dp[i]为以str[i]开头的后缀的ans,dp[i]=segma(

uva 1291 dp

UVA 1291 - Dance Dance Revolution 有一个跳舞机.原点为0,有四个方向,上左下右,分别标成(1234),初始玩家两只脚站在 0 位置,跳舞机会给出一串数字,玩家要按照顺序踩下四个方向的数字.移动脚会消耗玩家的能量,从0位置移动到四个方向消耗2点能量,从一个方向移动到另一个相邻的方向消耗3点能量,从一个方向移动到相反方向消耗4点能量,原点踩一下消耗1点能量.问你踩出这串数子最少要花多少能量. 根据能量消耗关系,我们可以发现当前两只脚踩的方向才是重点.然而要记录两只脚

uva 10534 dp

UVA 10534 - Wavio Sequence 定义一种 Wavio 的序列.其长度为2*n+1,前n+1严格递增,后n+1个严格递减. 求在给的序列中找一个最长的 Wavio 子序列.输出长度. 正向LIS求出每个点以该点为结尾的最长上升子序列长度p[i],然后反向LIS求出以该点位开头的最长递减子序列长度q[i]. 然后枚举 Wavio 子序列的中点,该店的 Wavio 长度为 2 * min(p[i], q[i]) - 1; #include <cstdio> #include &

UVA 147- Dollars(dp之子集和问题)

题目地址:UVA 147 题意:给定11种面值分别为100元, 50元, 20元, 10元, and 5元 and 2元, 1元, 50分, 20分, 10分 and 5分的钱,现在给定一个钱数,求出可以组成的种类数. 思路:子集和问题:S={ x1 , x2 ,-, xn }是一个正整数的集合,c是一个正整数.子集和问题判定是否存在S的一个子集S1,使得s1中的各元素之和等于c. 最突出的事例就是硬币计数问题:设c(i,j)是a1,a2--ai中包含ai且数和为j的方案数,显然目标是求c(n,

uva 11404 dp

UVA 11404 - Palindromic Subsequence 求给定字符串的最长回文子序列,长度一样的输出字典序最小的. 对于 [l, r] 区间的最长回文串,他可能是[l+1, r] 和[l, r-1]两个区间的结果.或者当s[l] == s[r]时,区间[l+1, r-1]的结果再加上以s[l], s[r]为首尾的子序列. dp[l][r] = ans(dp[l][r-1], dp[l+1][r], s[l] + dp[l+1][r-1] + s[r]) dp存的是子序列,即一个s

uva 11552 dp

UVA 11552 - Fewest Flops 一个字符串,字符串每 k 个当作一组,组中的字符顺序可以重组.问经过重组后改字符串可以编程最少由多少块字符组成.连续的一段字符被称为块. dp[i][j] 表式第i组以字符j结尾的最少块数. 那么我们考虑添加一组后可以减少块数的情况. 1):上一组的结尾在这一组里找得到同样的字符,并且该字符不作为当前块的结尾.如果要作为结尾的话要把该字符所在的块拆开,所以然并卵. 2):当前组只有一种字符,并且和上一组的结尾相同. 这两种情况都可以使块数减一 d