uva 1424 (dp专组G题)

来源:互联网 发布:淘宝卖家客服人工服务 编辑:程序博客网 时间:2024/06/07 09:17

链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36240

题意,

给定一个包含n(n<=100)个点的无向连通图和一个长度为L的序列A(L<=200),你的任务是修改尽量少的数,使得序列中的任意两个相邻的数或者相同,或者对应图中两个相邻结点。

题解:

用矩阵a存图,如果i,j之间有边置a[i][j] = a[j][i] = 1,并把正对角线也置1,等价于点和它本身连线。

用数组f存给定的序列A

用dp[i][k]表示在第i位为k时需要修改的最小的次数。

则可知dp[0][i] = (f[i]!=i).

动态转移方程为dp[i][k] = min(dp[i][k],dp[i-1][j] + f[i] != k);其中j为1~n1中所有a[j][k] = 1的值;

最后dp[n-1][i](1<=i<=n1)中的最小值即为所求。

本题错点:(我自己的)

要注意边界范围。

代码如下:

#include<bits/stdc++.h>using namespace std;const int maxn = 105;const int INF = 0x3f3f3f3f;int a[maxn][maxn];int d[2*maxn][maxn];int f[2*maxn];int main(){    int T;    cin>>T;    while(T--){        int n1,n2;        cin>>n1>>n2;        memset(a,0,sizeof(a));        for(int i = 1;i<=n1;i++)a[i][i] = 1;        for(int i= 0;i<n2;i++){            int x,y;            cin>>x>>y;            a[x][y] = a[y][x] = 1;        }        int n;        cin>>n;        memset(d,INF,sizeof(d));        for(int i = 0;i<n;i++)cin>>f[i];        for(int i = 1;i<=n1;i++)d[0][i] = (f[0] != i);        for(int i = 1;i<n;i++){            for(int k = 1;k<=n1;k++){                for(int j = 1;j<=n1;j++){                    if(a[k][j]){                        d[i][k] = min(d[i][k],d[i-1][j]+(f[i]!=k));                    }                }//                cout<<i<<" "<<k<<" "<<d[i][k]<<endl;            }        }        int ans = INF;        for(int i = 1;i<=n1;i++){            ans = min(ans,d[n-1][i]);        }        cout<<ans<<endl;    }}


1 0
原创粉丝点击