动态规划(模型转换):uvaoj 1625 Color Length

本文探讨了一道看似复杂的动态规划问题,通过巧妙地转换模型,将问题简化为易于处理的状态,利用C++实现了解决方案。重点在于理解如何拆分问题并将其转化为状态转移方程,最终求解最优路径或方案。

[PDF Link]题目点这里

  这道题一眼就是动态规划,然而貌似并不好做。

  如果不转换模型,状态是难以处理的。

  巧妙地转化:不直接求一种字母头尾距离,而是拆开放到状态中。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=5010;
 6 char s1[maxn],s2[maxn];
 7 int B1[26],E1[26],B2[26],E2[26];
 8 int dp[maxn][maxn];
 9 int add[maxn][maxn];
10 int main(){
11     int T,len1,len2;
12     scanf("%d",&T);
13     while(T--){
14         scanf("%s",s1+1);
15         scanf("%s",s2+1);
16         len1=strlen(s1+1);
17         len2=strlen(s2+1);
18         memset(B1,127,sizeof(B1));
19         memset(E1,-1,sizeof(E1));
20         memset(B2,127,sizeof(B2));
21         memset(E2,-1,sizeof(E2));
22         for(int i=1;i<=len1;i++){
23             s1[i]-='A';
24             if(B1[s1[i]]>len1)B1[s1[i]]=i;
25             E1[s1[i]]=i;
26         }
27         
28         for(int i=1;i<=len2;i++){
29             s2[i]-='A';
30             if(B2[s2[i]]>len2)B2[s2[i]]=i;
31             E2[s2[i]]=i;
32         }
33         
34         for(int i=0;i<=len1;i++)
35             for(int j=0;j<=len2;j++){
36                 if(i==j&&i==0)continue;
37                 if(!i||j&&dp[i][j-1]+add[i][j-1]<=dp[i-1][j]+add[i-1][j]){
38                     dp[i][j]=dp[i][j-1]+add[i][j-1];
39                     add[i][j]=add[i][j-1];
40                     if(B2[s2[j]]==j&&B1[s2[j]]>i)
41                         add[i][j]++;
42                     if(E2[s2[j]]==j&&E1[s2[j]]<=i)
43                         add[i][j]--;
44                 }
45                 if(!j||i&&dp[i][j-1]+add[i][j-1]>dp[i-1][j]+add[i-1][j]){
46                     dp[i][j]=dp[i-1][j]+add[i-1][j];
47                     add[i][j]=add[i-1][j];
48                     if(B1[s1[i]]==i&&B2[s1[i]]>j)
49                         add[i][j]++;
50                     if(E1[s1[i]]==i&&E2[s1[i]]<=j)
51                         add[i][j]--;
52                 }
53             }
54         printf("%d\n",dp[len1][len2]);    
55     }
56     return 0;
57 }

 

转载于:https://www.cnblogs.com/TenderRun/p/5303318.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值