LA 2257 动态规划

题意:无向图中有n个点,编号1~n,可以从一点走到相邻某点,也可以原地不动,这样得到一条路径的描述。

例如下图所示的无向图中,路径[1 2 2 7 5 5 5 7 4]是错误的,因为2不能到达7,  [1 2 2 4 5 5 5 7 4], [1 2 4 7 5 5 5 7 4], or [1 2 2 6 5 5 5 7 4]都是正确的,

定义两条路径A和B的距离dist(A, B) = sum d(ai, bi)   ,其中若ai==bi, d(ai, bi)=1  否则d(ai, bi)=0。。

给定一条路径A,求一条正确路径B,使AB的距离 dist(A, B) 最小。

分析:dp(i, v)表示第 i 步为点 v 的最小距离,dp(i, v) = min dp(i-1,u)+t.    (u到v有边,若Ai==v, t=0, 否则t=1.)         

 

 

const int N = 105, M = 10000;
int n, m;

int a[N<<1], len;//错误路径
int dp[2][N<<1], p, q;//dp[i][j]表示第i个点为j的最小dist   p q滚动数组

int head[N];

struct node{//
    int v, next;
}e[M];

void DP(){
    p = 0;
    memset(dp[p], 0, sizeof dp[p]);
    FOE(i, 1, len){
        q = 1-p;
        memset(dp[q], -1, sizeof dp[q]);
        FOE(u, 1, n){
            for(int j = head[u]; j!=-1; j=e[j].next){
                int v = e[j].v;
                checkmin(dp[q][v], dp[p][u]+(a[i]!=v));
            }
        }
        p = q;
    }

    int ans = -1;
    FOE(i, 1, n) checkmin(ans, dp[q][i]);
    printf("%d\n", ans);
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        p = 0;
        memset(head, -1, sizeof head);
        FOR(i, 0, m){
            int x, y;
            scanf("%d%d", &x, &y);
            e[p].v=y; e[p].next=head[x]; head[x]=p++;
            e[p].v=x; e[p].next=head[y]; head[y]=p++;
        }
        FOE(i, 1, n) {//到自己的边
            e[p].v=i; e[p].next=head[i]; head[i]=p++;
        }
        scanf("%d", &len);
        FOE(i, 1, len) scanf("%d", &a[i]);

        DP();
    }

    return 0;
}

 

          

posted @ 2013-05-29 21:26  心向往之  阅读(126)  评论(0编辑  收藏  举报