UVA 1424-Salesmen(DP)

题目大意:给出一个连通图和一个序列,求改变尽量少的序列中的元素,使得相邻两个元素相同或在图中相邻。

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

UVA 1424-Salesmen(DP)的相关文章

【UVa】Salesmen(dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4170 d[i,j]前i个字符j结尾 d[i,j]=min{d[i-1,k], j和k有边}+(a[i]!=j) 初始化d[1,j]=1, d[1,a[1]]=0 #include <cstdio> #include <cstring> #include <cma

UVA 1371 - Period(DP)

6.4 一些说明 数据属性可以重写同名的方法属性.这是为了避免在大型系统中产生问题的意外名称冲突.所以用一些减少冲突的常用方法是很有效果的.常用的方法包括:大写字母方法名称,用唯一的字符串来做为数据属性的名称(可以是个下划线_)或者用动词命名方法和用名字命名数据属性. 数据属性就像和对象的普通用户一样可以被方法引用.换句话说,类不能用来实现纯净的数据类型.事实上,在python中不能强制数据隐藏,一切基于约定.(另一方面,如C中写的,python的实现可以做到完全隐藏实现细节并且在必要是可以控制

uva 10271 Chopsticks (DP)

uva 10271 ChopsticksA 题目大意:给出客人数K和筷子数量N(支),总人数M=客人数K + 8(还有家人).要找出M组筷子,每组包括3支筷子,每组都有一个badness值,badness值为每组中较小的两支筷子的差值.求怎样分组,才能使总差值最小. 解题思路:dp[i][j]表示使用第i支筷子,并已组成j组是的最小badness总值.在取筷子时,要注意在所有未被使用的筷子中,要有比选取的两根筷子更长的筷子. #include <cstdio> #include <cst

【UVa】Jump(dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4198 约瑟夫变形 根据f(n)=(f(n-1)+m)%n 因为是求倒数第几个 那么我们只要求出f(倒数第几个)的值然后再带进去即可. (没理解的自行面壁..) 而f(倒数第几个)=(m-1)%倒数第几个 然后就行了.. #include <cstdio> #include <

Uva 10465-Homer Simpson(DP)

题目链接:点击打开链接 DAG上的最长路. 题意:相当于给两种硬币的面值,每种可以用无限次,问恰好组成S 最多能用多少个硬币.如果不能恰好组成S,输出最大能组成的面值x(x<S)所需的最大硬币数 和 S-x. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <string> #include <cctype&

UVA 10163-Storage Keepers(DP)

题目大意:有N(1<=N<=100)个仓库需要看管,有M(1<=M<=30)名应聘者,每个人有能力属性Pi(1<=Pi<=1000).所有仓库都是一样的,每个仓库只能被一人看守,一人可看守多个仓库,当一人看守u个仓库时,每个仓库的安全度为Uj=Pi/u,总安全度为min Uj.雇佣一个能力值为Pi的人需要花费Pi元.求最大的总安全度,和在这样的情况下的最小花费. 先dp一次,求出可能的最大总安全度max,再次dp,求出在安全度为max下的最小花费. 第一次dp:用d[i

UVA 1366-Martian Minging(DP)

题目大意:有一个n(1<=n<=500)行m(1<=m<=500)列的网格,每个网格有两种矿,yeyenum和bloggium,在网格的西边是yeyenum的精炼厂,北边是bloggium的精炼厂,每个网格有一定数量的两种矿,现在要安排一个传送带系统,传送带只能由南向北或者由东向西,传送带同方向的可以连续传,只有传到相应精炼厂才是有效的,问许多能拿到多少矿. 用d[i][j]表示到第i行第j列时,前i行j列能产生的最大的矿数量,用a[i][j]表示在第i行从第1列加到第j列的yey

UVA 473-Raucous Rockers(DP)

题目大意:有n首歌,m个光盘,每个光盘最多能放t时间的歌,给出每首歌的长度,必须按顺序录入光盘(可以选择不录某几首歌),最多能录多少首歌. 用d[i][j][0]表示前i首歌,放j首,最少用多少个光盘,用d[i][j][1]表示前i首歌,放j首,在光盘最少的前提下,最后一个光盘可以剩余的最多容量.根据是否放第i首歌完成递推. 这样递推是正确的,因为前i首歌,放j首的情况下,最佳的情况就是尽量少的用光盘,并且使得最后一个光盘容量尽量大(例如如果用的光盘数多一些,并且最后一个光盘的容量更大一些,这样

Uva 562-Dividing coins(DP)

题目链接:点击打开链接 题意:n个硬币,给出每个硬币的价值,要求把这些硬币分成两组,使得两组的价值差尽量小. 可以发现如果可以平分,那么价值差肯定为0,那么依次从sum/2 --> 0 枚举i,如果用上述硬币的价值组合可以组成i 那么sum-i-i就是答案.如何判断是否对于一个数i用这些硬币可以凑出来,用背包判就可以了,注意是01背包. #include <algorithm> #include <iostream> #include <cstring> #inc

UVA 11081 Strings(DP)

Given 3 strings of only lowercase letter you have to count the number of ways you can construct the third string by combining two subsequences from the first two strings. After deleting 0 or more characters from a string we can get its subsequence. F