UVALive 4256 Salesmen

来源:互联网 发布:十三经注疏 知乎 编辑:程序博客网 时间:2024/04/30 21:52

    树形dp入门题。找出给出路径最相近路径,输出路径上不同节点个数。其实就是dfs + 记忆化。

    也可用递推得出答案,个人觉得记忆化的方法容易理解和方便书写。

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;const int N = 111;const int M = 11111;const int INF = 1e7;int first[N], next[M];int dp[N][N << 1], num, k;bool vis[N][N << 1];int path[N << 1];struct Edge{    int u, v;}E[M];void add_edge(int u, int v){    E[num].u = u, E[num].v = v;    next[num] = first[u], first[u] = num ++;}int dfs(int u, int step)//当前节点u,步数step。{    int i, j, ret, v;    if(step == k) return 0;    if(vis[u][step]) return dp[u][step];    vis[u][step] = 1;    ret = dfs(u, step + 1);    for(i = first[u]; ~i; i = next[i])    {        v = E[i].v;        ret = min(ret, dfs(v, step + 1));    }    if(u != path[step]) ret ++;    return dp[u][step] = ret;}int main(){    //freopen("input.txt", "r", stdin);    int n, m, u, v, i, j, t, ans;    scanf("%d", &t);    while(t --)    {        scanf("%d%d", &n, &m);        num = 0;        memset(first, -1, sizeof(first));        for(i = 0; i < m; i ++)        {            scanf("%d%d", &u, &v);            add_edge(u, v);            add_edge(v, u);        }        scanf("%d", &k);        for(i = 0; i < k; i ++)        {            scanf("%d", &path[i]);        }        ans = INF;        memset(vis, 0, sizeof(vis));        for(i = 1; i <= n; i ++)        {            ans = min(ans, dfs(i, 0));        }        printf("%d\n", ans);    }}


 

原创粉丝点击