UVA 1625 颜色长度

题目描述:入门经典 p276

先输入一个整数n表示查询多少次,后面接n对颜色串(一共2n条)这是一个比较特殊的动态规划,哪特殊呢?它比较的对象不同,标准不一样,比如01背包比较的标准是让价值最大化,价值是可以直接算出来的,而这条题是比较L©和最小,这是不可以直接算出来的,要间接求解来比较,理解了这个间接求解,那么下面就很简单了
想法:用 f[i] [j] ,表示从A颜色串拿i 个字符,B颜色串拿 j 个字符;
num[i][j] 表示从A,B颜色串中拿i j个字符来排列,具体顺序我们先不管,我们只知道这个意义:它代表的是这个序列中有多少个未排完的元素,就是说该L©还是未定的,后面还有相同的颜色。 然后设sum为所有L©的和,那么你会发现如果再加入一个元素,那么sum的值会加上num[i][j] ,我们就是通过这个来比较大小的。间接法来求比较的标准。
所以我们有状态转移方程: f[i][j]=min(f[i][j-1],f[i-1][j])+num[i][j]
这样我们又要求出所有num[i][j],那么如何来确定这个num[i][j]
实际上 num[i][j]=num[i][j-1]+judge(j)judge表示j这个B[j],加入后B[j]所代表的颜色是否到了终点,是则-1,如果B[j]是"新来的"那么+1,再不然为0.接下来就可以愉快的写代码了,f[i][j]用了优化空间的方法,如果不知道,可以去其他地方找找背包的空间优化的问题。另外我用M[200]来统计所有颜色的个数,用其他如m[200],aa[200],bb[200]来统计目前序列中颜色个数,代码如下:

#include
#include
#include
using namespace std;
int  M[200];//可以理解为大地图,所有颜色的信息
char A[5005],B[5005];
int f[5005];
int num[5005][5005];
void pn(int a,int b)//调试用的函数,可删
{
 for(int i=0;i<=a;i++)
 {
  for(int j=0;j<=b;j++)
   cout<>n;
 while(n--)//询问n次
 { memset(M,0,sizeof(M));
  cin>>A>>B;
  int a,b,i;
  int aa[200]={},bb[200]={};
  for(i=0;A[i]!='\0';i++)//统计A颜色串的个数,顺便求其长度
    M[A[i]]++;
  a=i;
  for(i=0;B[i]!='\0';i++)//上同
    M[B[i]]++;
  b=i;
num[0][0]=0;//所有的数从这里推导,因为要询问多次,所以必须滴
  for(i=0;i

你可能感兴趣的:(UVA 1625 颜色长度)