夏夜、

心若平似镜、何题不AC。

UVA 1424 \ uvalive 4256 Salesmen 简单DP

题意:

给一个无向连通图,和一个长度为L的序列。任务是修改序列上的某些数使得每相邻两个数相等或在图上是两个相邻的点。最少需要修改几个数?

用dp[n][fa]表示当第n+1个数是fa时前n个数最少要修改几次

用邻接矩阵存图,补上g[i][i]=1;g[0][i]=1;就可以不用分别考虑相等和初始的状态了

dp[n][fa]=min{dp[n-1][v]+(v==an?0:1) | g[fa][v]==1 }

int g[110][110];
int da[210];
int dp[210][110];
int f(int n,int fa,int N)
{
    if(dp[n][fa]>=0)return dp[n][fa];
    if(n==0)return 0;
    int num=INF;
    for(int i=1;i<=N;i++)
    {
        if(g[i][fa])
        {
            num=min(num,f(n-1,i,N)+(i==da[n]?0:1));
        }
    }
    return dp[n][fa]=num;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        memset(g,0,sizeof(g));
        int n1,n2;
        scanf("%d%d",&n1,&n2);
        for(int i=1;i<=n2;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            g[a][b]=g[b][a]=1;
        }
        for(int i=1;i<=n1;i++)g[0][i]=g[i][0]=1;
        for(int i=1;i<=n1;i++)g[i][i]=1;
        int n3;
        scanf("%d",&n3);
        for(int i=1;i<=n3;i++)scanf("%d",&da[i]);
        memset(dp,-1,sizeof(dp));
        int num=f(n3,0,n1);
        printf("%d\n",num);
    }
    return 0;
}
View Code

 

posted on 2013-08-10 16:43  BMan、  阅读(367)  评论(0编辑  收藏  举报

导航