基德KID.1412 发表于 2013-2-4 22:09:19

【DP最大公共子序列】HDU 1159/1080/1503

KIDx的解题报告
 
第一题(比较简单,不详细解):
HDU 1159 Common Subsequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159
 
题意:求两个串的最长公共子序列

代码中的dp表示0到i-1跟0到j-1的最长公共子序列
 
#include <iostream>using namespace std;#define M 5005int dp;char a, b;int main(){    int i, j, la, lb;    while (~scanf ("%s%s", a, b))    {      la = strlen (a), lb = strlen (b);      for (i = 0; i < la; i++)//边界初始化            dp = 0;      for (j = 0; j < lb; j++)            dp = 0;      for (i = 1; i <= la; i++)      {            for (j = 1; j <= lb; j++)            {//状态转移                if (a == b)                  dp = dp + 1;                else dp = max (dp, dp);            }      }      printf ("%d\n", dp);    }    return 0;} 
 
第二题:
HDU 1080 Human Gene Functions
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1080
 
题意:两个字符串,每个字符串中都可以插入'-',保证最后两串的长度相等,之后让两串对齐,两串相同位置的字母组成的字符匹配有一个值,问这些值的和最大是多少,是第一题的变形
下图为字符匹配所得价值的表
http://dl.iteye.com/upload/attachment/0064/5755/6dec206f-e7f3-37c2-a7f2-c596c5076788.gif
dp表示0到i-1跟0到j-1配对的最大价值
 
状态转移:
①dp由dp转移过来,代价是a跟'-'匹配
②由dp转移过来,代价是b跟'-'匹配
③由dp转移过来,代价是a跟b匹配

#include <iostream>#include <algorithm>using namespace std;#define inf 0x3fffffff#define M 105int dp, v = {0};char a, b; int main(){    v = v = v = v = 5;    v = v = -1;    v = v = -2;    v = v = -1;    v = v = -3;    v = v = -2;    v = v = -2;    v = -3;//7表示'-',0,2,6,19分别表示A,C,G,T    v = -4;    v = -2;    v = -1;    int i, j, la, lb, t;    scanf ("%d", &t);    while (t--)    {      scanf ("%d%s%d%s", &la, a, &lb, b);      for (i = 0; i <= la; i++)            for (j = 0; j <= lb; j++)                dp = -inf;      dp = 0;      for (i = 1; i <= la; i++)//一系列的边界初始化            dp = dp + v-'A'];      for (j = 1; j <= lb; j++)            dp = dp + v-'A'];      for (i = 1; i <= la; i++)      {            for (j = 1; j <= lb; j++)            {//状态转移方程                dp = max (dp,                        max (dp+v-'A']-'A'],                        max (dp+v-'A'],                        dp+v-'A'])));            }      }      printf ("%d\n", dp);    }    return 0;} 

 第三题:

HDU 1503 Advanced Fruits
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1503
题意:
给你两个单词,然后你要把两个单词拼接成一个新单词,使得新单词的子序列中包含两个单词,并且要使这个新单词最短
基本思路:
求最长公共子序列,令这个序列只输出一次就可以使新单词最短
记录路径:
增加二维数组road记录状态转移路径
road = 0 表示road由road转移过来,即a与b属于最长公共子序列中的元素,扫描路径时将hash赋值为j-1表示a串的i-1匹配b串的j-1【其中hash初始时全为-1】
road = 1 表示road由road转移过来
road = 2 表示road由road转移过来
输出答案:
先设置start变量【表示b串的当前位置】,扫描a串
①当对于a有hash==-1,说明a不是最长公共子序列中的元素,直接输出并且continue;
②否则b串输出从start到hash的值,因为a跟b]匹配嘛,所以输出b]就不用输出a勒,然后start变为hash + 1;


 
 
#include <iostream>using namespace std;#define M 105int dp, road, hash;char a, b;int main(){    int i, j, la, lb;    while (~scanf ("%s%s", a, b))    {      la = strlen (a), lb = strlen (b);      for (i = 0; i < la; i++)            dp = 0;      for (j = 0; j < lb; j++)            dp = 0;      memset (road, -1, sizeof(road));      for (i = 1; i <= la; i++)      {            for (j = 1; j <= lb; j++)            {                if (a == b)                {                  dp = dp + 1;                  road = 0;                }                else                {                  if (dp > dp)                        dp = dp, road = 1;                  else dp = dp, road = 2;                }            }      }      int k = 0;      memset (hash, -1, sizeof(hash));      i = la, j = lb;      while (road != -1)//扫描最长公共序列路径      {            if (road == 0)            {                i--, j--;                hash = j;            }            if (road == 2)                j--;            if (road == 1)                i--;      }      int start = 0;//b串的还没打印的第一个字母的位置      for (i = 0; i < la; i++)      {            if (hash == -1)//不属于最长公共子序列的元素            {                printf ("%c", a);                continue;            }//a与b]匹配,属于最长公共子序列            for (j = start; j <= hash; j++)                printf ("%c", b);            start = hash + 1;      }      for (j = start; j < lb; j++)            printf ("%c", b);      printf ("\n");    }    return 0;} 
 
页: [1]
查看完整版本: 【DP最大公共子序列】HDU 1159/1080/1503