递推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 /************************************************
 8 Author        :Running_Time
 9 Created Time  :2015-8-5 9:03:34
10 File Name     :UVA_1424.cpp
11  ************************************************/
12
13 #include <cstdio>
14 #include <algorithm>
15 #include <iostream>
16 #include <sstream>
17 #include <cstring>
18 #include <cmath>
19 #include <string>
20 #include <vector>
21 #include <queue>
22 #include <deque>
23 #include <stack>
24 #include <list>
25 #include <map>
26 #include <set>
27 #include <bitset>
28 #include <cstdlib>
29 #include <ctime>
30 using namespace std;
31
32 #define lson l, mid, rt << 1
33 #define rson mid + 1, r, rt << 1 | 1
34 typedef long long ll;
35 const int MAXN = 1e2 + 10;
36 const int INF = 0x3f3f3f3f;
37 const int MOD = 1e9 + 7;
38 bool con[MAXN][MAXN];
39 int a[MAXN*2];
40 int dp[MAXN*2][MAXN];
41 int n1, m, n;
42
43 int work(void)  {
44     memset (dp, INF, sizeof (dp));
45     for (int i=1; i<=n1; ++i)   {
46         dp[1][i] = (i != a[1]);
47     }
48     for (int i=2; i<=n; ++i)    {
49         for (int j=1; j<=n1; ++j)   {
50             for (int k=1; k<=n1; ++k)   {
51                 if (con[j][k])  {
52                     dp[i][j] = min (dp[i][j], dp[i-1][k] + (j != a[i]));
53                 }
54             }
55         }
56     }
57     int res = INF;
58     for (int i=1; i<=n1; ++i)    {
59         res = min (res, dp[n][i]);
60     }
61
62     return res;
63 }
64
65 int main(void)    {     //UVA 1424 Salesmen
66     int T;  scanf ("%d", &T);
67     while (T--) {
68         scanf ("%d%d", &n1, &m);
69         memset (con, false, sizeof (con));
70         for (int i=1; i<=n1; ++i)   con[i][i] = true;
71         for (int i=1; i<=m; ++i)    {
72             int u, v;   scanf ("%d%d", &u, &v);
73             con[u][v] = con[v][u] = true;
74         }
75         scanf ("%d", &n);
76         for (int i=1; i<=n; ++i)    {
77             scanf ("%d", &a[i]);
78         }
79
80         printf ("%d\n", work ());
81     }
82
83     return 0;
84 }

  1 /************************************************
  2 Author        :Running_Time
  3 Created Time  :2015-8-5 9:03:34
  4 File Name     :UVA_1424.cpp
  5  ************************************************/
  6
  7 #include <cstdio>
  8 #include <algorithm>
  9 #include <iostream>
 10 #include <sstream>
 11 #include <cstring>
 12 #include <cmath>
 13 #include <string>
 14 #include <vector>
 15 #include <queue>
 16 #include <deque>
 17 #include <stack>
 18 #include <list>
 19 #include <map>
 20 #include <set>
 21 #include <bitset>
 22 #include <cstdlib>
 23 #include <ctime>
 24 using namespace std;
 25
 26 #define lson l, mid, rt << 1
 27 #define rson mid + 1, r, rt << 1 | 1
 28 typedef long long ll;
 29 const int MAXN = 1e2 + 10;
 30 const int INF = 0x3f3f3f3f;
 31 const int MOD = 1e9 + 7;
 32 bool con[MAXN][MAXN];
 33 vector<int> G[MAXN];
 34 vector<int> pre;
 35 int a[MAXN*2];
 36 int dp[MAXN][2][MAXN];
 37 int n1, m, n;
 38
 39 int work(void)  {
 40     memset (dp, INF, sizeof (dp));    pre.clear ();
 41     dp[1][0][a[1]] = 0;
 42     for (int i=1; i<=n1; ++i)   {
 43         if (i == a[1])  continue;
 44         pre.push_back (i);
 45         dp[1][1][i] = 1;
 46     }
 47     for (int i=2; i<=n; ++i)    {
 48         if (con[a[i-1]][a[i]])  {
 49             dp[i][0][a[i]] = dp[i-1][0][a[i-1]];
 50             pre.clear ();   continue;
 51         }
 52         vector<int> tmp;
 53         for (int j=0; j<pre.size (); ++j)   {
 54             int u = pre[j];
 55             for (int k=0; k<G[u].size (); ++k) {
 56                 int v = G[u][k];
 57                 if (con[u][v])  {
 58                     if (v == a[i])  dp[i][0][v] = min (dp[i][0][v], dp[i-1][1][u]);
 59                     else    dp[i][1][v] = min (dp[i][1][v], dp[i-1][1][u] + 1);
 60                     tmp.push_back (v);
 61                 }
 62             }
 63         }
 64         pre.clear ();
 65         for (int j=0; j<tmp.size (); ++j)   pre.push_back (tmp[j]);
 66     }
 67
 68     int res = INF;
 69     res = min (res, dp[n][0][a[n]]);
 70     for (int i=0; i<pre.size (); ++i)   {
 71         int v = pre[i];
 72         res = min (res, dp[n][1][v]);
 73     }
 74
 75     //debug
 76     for (int i=1; i<=n; ++i)    {
 77         printf ("%d ", dp[i][0][a[i]]);
 78     }
 79     puts ("");
 80
 81     return res;
 82 }
 83
 84 int main(void)    {
 85     int T;  scanf ("%d", &T);
 86     while (T--) {
 87         scanf ("%d%d", &n1, &m);
 88         memset (con, false, sizeof (con));
 89         for (int i=1; i<=n1; ++i)   G[i].clear ();
 90         for (int i=1; i<=n1; ++i)   con[i][i] = true;
 91         for (int i=1; i<=m; ++i)    {
 92             int u, v;   scanf ("%d%d", &u, &v);
 93             con[u][v] = con[v][u] = true;   G[u].push_back (v); G[v].push_back (u);
 94         }
 95         scanf ("%d", &n);
 96         for (int i=1; i<=n; ++i)    {
 97             scanf ("%d", &a[i]);
 98         }
 99
100         printf ("%d\n", work ());
101     }
102
103     return 0;
104 }

undone(感受一下就行了)

时间: 2024-08-25 02:43:48

递推DP UVA 1424 Salesmen的相关文章

递推DP UVA 607 Scheduling Lectures

题目传送门 题意:教授给学生上课,有n个主题,每个主题有ti时间,上课有两个限制:1. 每个主题只能在一节课内讲完,不能分开在多节课:2. 必须按主题顺序讲,不能打乱.一节课L时间,如果提前下课了,按照时间多少,学生会有不满意度.问最少要几节课讲完主题,如果多种方案输出不满意度最小的 分析:dp[i]表示前i个主题最少要多少节课讲完,那么这个主题可能和上个主题在同一节课讲或者多开新的一节课讲,状态转移方程:看代码:优先满足节数少的情况 收获:普通的递推DP 代码: /**************

递推DP UVA 1366 Martian Mining

题目传送门 1 /* 2 题意:抽象一点就是给两个矩阵,重叠的(就是两者选择其一),两种铺路:从右到左和从下到上,中途不能转弯, 3 到达边界后把沿途路上的权值相加求和使最大 4 DP:这是道递推题,首先我题目看了老半天,看懂后写出前缀和又不知道该如何定义状态好,写不出状态转移方程,太弱了. 5 dp[i][j]表示以(i, j)为右下角时求得的最大值,状态转移方程:dp[i][j] = max (dp[i-1][j] + sum1[i][j], dp[i][j-1] + sum2[i][j])

递推DP UVA 1291 Dance Dance Revolution

题目传送门 1 /* 2 题意:给一串跳舞的动作,至少一只脚落到指定的位置,不同的走法有不同的体力消耗,问最小体力消费多少 3 DP:dp[i][j][k] 表示前i个动作,当前状态(j, k)的最小消费,状态转移方程:(a[i], k) <- min (a[i-1], k) + cost 4 以及(a[i-1], a[i]) <- min (a[i-1], k) + cost, (k, a[i])和(a[i], a[i-1])情况类似,最后再去最小值就行了 5 */ 6 /*********

递推DP UVA 590 Always on the run

题目传送门 题意:题意难懂,就是一个小偷在m天内从城市1飞到城市n最小花费,输入的是每个城市飞到其他城市的航班. 分析:dp[i][j] 表示小偷第i天在城市j的最小花费.状态转移方程:dp[i][j] = min (dp[i-1][k] + cost[k][j][t%day]) t表示在t天时k飞往j的飞机的花费 收获: 代码: /************************************************ * Author :Running_Time * Created

hdu 1284 钱币兑换问题 (递推 || DP || 母函数)

钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5069    Accepted Submission(s): 2868 Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. Input 每行只有一个正整数N,N小于32768. Outpu

D. Caesar&#39;s Legions 背包Dp 递推DP

http://codeforces.com/problemset/problem/118/D 设dp[i][j][k1][k2] 表示,放了i个1,放了j个2,而且1的连续个数是k1,2的连续个数是k2 如果这样写,用dfs写是很简单的.但是超时,我记忆化不到 如果用递推写,对于每一个状态,更新到下一个状态. 如果放的是1,那么新的状态是dp[i + 1][j][k1 + 1][0]也就是,用多了一个1,而且连续的个数也增加了.同时,2的连续个数就打破了,变成了0 这种枚举旧状态,更新下一个状态

递推DP URAL 1031 Railway Tickets

题目传送门 1 /* 2 简单递推DP:读题烦!在区间内的都更新一遍,dp[]初始化INF 3 注意:s1与s2大小不一定,坑! 4 详细解释:http://blog.csdn.net/kk303/article/details/6847948 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9 #include <cstring> 10 #include <s

递推DP URAL 1119 Metro

题目传送门 1 /* 2 题意:已知起点(1,1),终点(n,m):从一个点水平或垂直走到相邻的点距离+1,还有k个抄近道的对角线+sqrt (2.0): 3 递推DP:仿照JayYe,处理的很巧妙,学习:) 4 好像还要滚动数组,不会,以后再补 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9 #include <cmath> 10 #include <cs

Code Force 429B Working out【递推dp】

Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the beach. The gym where they go is a matrix a with n lines and mcolumns. Let number a[i][j] represents the calories burned by performing workout at the