题目大意:给定一个包含n个点的无向图和一个长度为L的序列A,要求修改尽量少得数,使得序列中的任意两个相邻数相等或者在途中相邻。
解题思路:dp[i][j]表示说长度为i且最后一个数为j的情况需要修改最少几次。dp[i][j] = min(dp[i][j], dp[i-1][k] + (j == A[i])?1:0));
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 105; const int INF = 0x3f3f3f3f; int n, m, k, g[N][N], A[2*N], dp[N*2][N]; void init () { int a, b; memset(g, 0, sizeof(g)); memset(dp, INF, sizeof(dp)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) dp[0][i] = 0; for (int i = 0; i < m; i++) { scanf("%d%d", &a, &b); g[a][b] = g[b][a] = 1; } scanf("%d", &k); for (int i = 1; i <= k; i++) scanf("%d", &A[i]); } int solve() { int ans = k; for (int i = 1; i <= k; i++) { for (int j = 1; j <= n; j++) { for (int t = 1; t <= n; t++) if (j == t || g[j][t]) { dp[i][j] = min(dp[i][j], dp[i-1][t]+(j == A[i] ? 0 : 1)); } } } for (int i = 1; i <= n; i++) { ans = min(dp[k][i], ans); } return ans; } int main () { int cas; scanf("%d", &cas); while (cas--) { init(); printf("%d\n", solve()); } return 0; }
原文:http://blog.csdn.net/keshuai19940722/article/details/19417801