uva 4256题解(简单dp)

题干是给定n个点连通图和一个序列,修改尽量少的数,使得序列中的任意两个相邻数或相等,或相连

思路是用d[i][j]表示以j结尾的前i个数的最小修改次数,那么最后的答案为min(d[n][j])

状态总数为o(n^2),转移为o(n),决策为o(1),故时间复杂度为o(n^3);

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include 
#include
#include 
using namespace std;  
#define LL long long  


const int maxn=105;
const int maxl=205;
const int INF=100000000;


int d[maxl][maxn];
int G[maxn][maxn];
int A[maxl];


int main(){
	//freopen("input.txt","r",stdin);
	
	int t,n1,n2;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n1,&n2);
		
		memset(G,0,sizeof(G));
		for(int i=1;i<=n2;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			G[x][y]=G[y][x]=1;
		}
		for(int i=1;i<=n1;i++) G[i][i]=1;
		
		
		int n;scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&A[i]);
	    
		
		for(int i=1;i<=n1;i++) d[0][i]=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n1;j++){
				int flag=1;
				if(A[i]==j) flag=0;
				d[i][j]=INF;
				for(int k=1;k<=n1;k++){
					if(G[k][j]) d[i][j]=min(d[i-1][k]+flag,d[i][j]);
				}
			}
		}
		
		int ans=INF;
		for(int i=1;i<=n1;i++) ans=min(ans,d[n][i]);
		printf("%d\n",ans);
	}
	return 0;
} 

你可能感兴趣的:(程序设计竞赛)