题目大意:给出一个连通图和一个序列,求改变尽量少的序列中的元素,使得相邻两个元素相同或在图中相邻。
a[i][j]=1表示i和j相邻,a[i][j]=0表示i和j不相邻。b[i]表示序列中第i个数。
用d[i][j]表示前i个数且第i个数为元素j时的最少改变数量,由d[i-1][u]推来。其中j和u相同或相邻。
状态转移方程:d[i][j]=min { d[i-1][u]+k }(a[u][j]=1,u==b[i]时k=0,u!=b[i]时k=1)
#include<stdio.h> #include<stdlib.h> int a[110][110]; int b[210]; int d[210][110]; int main(void) { int i,j,u,v,p,n,m,pi,qi,min,minp; scanf("%d",&pi); for(qi=0;qi<pi;qi++) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { a[i][j]=0; } } for(i=1;i<=n;i++) { a[i][i]=1; } for(i=1;i<=m;i++) { scanf("%d%d",&u,&v); a[u][v]=a[v][u]=1; } scanf("%d",&p); for(i=1;i<=p;i++) { scanf("%d",&b[i]); } for(j=1;j<=n;j++) { if(j!=b[1]) { d[1][j]=1; } else { d[1][j]=0; } } for(i=2;i<=p;i++) { for(j=1;j<=n;j++) { if(b[i]==j) { minp=1000000000; for(u=1;u<=n;u++) { if((a[u][j]==1)&&(d[i-1][u]<minp)) { minp=d[i-1][u]; } } d[i][j]=minp; } else { minp=1000000000; for(u=1;u<=n;u++) { if((a[u][j]==1)&&(d[i-1][u]+1<minp)) { minp=d[i-1][u]+1; } } d[i][j]=minp; } } } min=d[p][1]; for(j=2;j<=n;j++) { if(d[p][j]<min) { min=d[p][j]; } } printf("%d\n",min); } return 0; }
时间: 2024-10-23 11:40:33