题意:
给你一个无向图,然后给你一条路径,然后要你修改此条路径(如果该条路径在图中是行得通的,则不需要修改,结果为0)。现在要你修改的点数最小,使得修改后的路径是正确的。
思路:
定义dp[i][j]:走了i步后,到达j的最小修改点数。
状态转移方程:
if(seq[i] == j)//与原路径点相同则不需要+1,
dp[i][j] = min(dp[i][j], dp[i-1][t]);
else
dp[i][j] = min(dp[i][j], dp[i-1][t] + 1);
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
const int MAXPOINT = 105;
const int MAXLEN = 205;
int gap[MAXPOINT][MAXPOINT];
int seq[MAXLEN];
int dp[MAXLEN][MAXPOINT];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(gap, 0, sizeof(gap));
int n, m;
int u, v;
scanf("%d%d",&n, &m);
for(int i = 0;i < m; i++)
{
scanf("%d%d", &u,&v);
gap[u][v] = gap[v][u] = 1;
}
for(int i = 1; i <= n; i++)
gap[i][i] = 1;
int len;
scanf("%d",&len);
for(int i = 1;i <= len; i++)
{
scanf("%d",&seq[i]);
}
memset(dp, -1, sizeof(dp));
for(int t = 1;t <= n; t++)
{
if(t == seq[1])
dp[1][t] = 0;
else
dp[1][t] = 1;
}
for(int i = 2;i <= len; i++)
{
for(int t = 1;t <= n; t++)//from t to j
{
for(int j = 1;j <= n; j++)
{
if(gap[t][j] == 0) continue;
if(seq[i] == j)
{
if(dp[i][j] == -1)
dp[i][j] = dp[i-1][t];
else
dp[i][j] = min(dp[i][j], dp[i-1][t]);
}
else
{
if(dp[i][j] == -1)
dp[i][j] = dp[i-1][t]+1;
else
dp[i][j] = min(dp[i][j],dp[i-1][t] + 1);
}
}
}
}
int res = dp[len][1];
for(int i = 1;i <= n; i++)
{
res = min(res, dp[len][i]);
}
printf("%d\n",res);
}
return 0;
}