HDU 2476 String painter(记忆化搜索, DP)

题目大意:

给你两个串,有一个操作! 操作时可以把某个区间(L,R) 之间的所有字符变成同一个字符。现在给你两个串A,B要求最少的步骤把A串变成B串。

题目分析:

区间DP, 假如我们直接想把A变成B,那么我们DP区间的时候容易产生一个问题:假如我这个区间更新了,那么之前这个区间的子区间内DP出来的值就没用。

然后考虑到这里一直想不过去。最后看了看题解才知道.

我们可以先预处理一下怎么将一个空串变成B串需要的操作数。

这样我们就不用考虑子区间被覆盖的情况了。

如区间L,R

我们需要考虑的是点L是否需要单独刷一次。

如果需要单独刷一次那么就是:dp[L][R] = dp[L+1][R] + 1;

如果不需要单独刷,那么就是从一个点k刷到点L的时候顺便把L给刷掉。

那么我们就不用再占用刷的次数了。

故:if(b[L] == b[k])  dp[L][R] = min(dp[L][R], dp[L+1][k] + dp[k+1][R]);

因此我们dp[L][R] 保存的就是最小刷的次数了。

然后下面我们把答案枚举一下就行了。

============================================================================================

记忆化搜索

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL INF = 0xfffffff;
const LL maxn = 105;
int dp[maxn][maxn], ans[maxn];
char a[maxn], b[maxn];
int DFS(int L,int R)
{
    if(dp[L][R])
        return dp[L][R];
    if(L == R)
        return dp[L][R] = 1;
    if(L > R)
        return 0;
    dp[L][R] = DFS(L+1,R) + 1;
    for(int k=L+1; k<=R; k++)
    {
        if(b[L] == b[k])
            dp[L][R] = min(dp[L][R], DFS(L+1,k) + DFS(k+1,R) );
    }
    return dp[L][R];
}

int main()
{

    while(cin >> a >> b)
    {
        memset(dp, 0, sizeof(dp));
        int n = strlen(a);
        for(int i=0; i<n; i++)
            DFS(0, i);

        for(int i=0; i <n; i++)
        {
            ans[i] = dp[0][i];
            if(a[i] == b[i])
                ans[i] =i?ans[i-1]:0;

            for(int j=0; j<i; j++)
                ans[i] = min(ans[i], ans[j]+dp[j+1][i]);
        }
        printf("%d\n", ans[n-1]);
    }
    return 0;
}

=========================================================================

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL INF = 0xfffffff;
const LL maxn = 105;
int dp[maxn][maxn], ans[maxn];
char a[maxn], b[maxn];

int main()
{

    while(cin >> a >> b)
    {
        memset(dp, 0, sizeof(dp));
        int n = strlen(a);        for(int len=0; len<n; len++)
        {
            for(int i=0; i+len<n; i++)
            {
                int j = i + len;
                dp[i][j] = dp[i+1][j] + 1;
                for(int k=i+1; k<=j; k++)
                {
                    if(b[i] == b[k])
                    {
                        dp[i][j] = min(dp[i][j], dp[i+1][k] + dp[k+1][j]);
                    }
                }
            }
        }

        for(int i=0; i <n; i++)
        {
            ans[i] = dp[0][i];
            if(a[i] == b[i])
                ans[i] =i?ans[i-1]:0;

            for(int j=0; j<i; j++)
                ans[i] = min(ans[i], ans[j]+dp[j+1][i]);
        }
        printf("%d\n", ans[n-1]);
    }
    return 0;
}
时间: 2024-12-28 01:32:08

HDU 2476 String painter(记忆化搜索, DP)的相关文章

hdu 4960 记忆化搜索 DP

Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 490    Accepted Submission(s): 180 Problem Description Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morni

hdu 2833 WuKong(最短路径+记忆化搜索)

http://acm.hdu.edu.cn/showproblem.php?pid=2833 大致题意:给定一个无向图,以及悟空和师傅起点与终点,求它们分别从起点到终点的最短路径中经过相同的点的最大个数. 思路:首先dijkstra求出最短路,那么如果有dis[a] + map[a][b] = dis[b],则边(a,b)一定在最短路径上.根据这一定理可以求出所有最短路径.然后类似于求最长公共子序列求经过的相同点的最大个数. 即若a==b ,dp[a][b] = max(dp[i][j]+1)

HDU 4597 Play Game(记忆化搜索,深搜)

题目 //传说中的记忆化搜索,好吧,就是用深搜//多做题吧,,这个解法是搜来的,蛮好理解的 //题目大意:给出两堆牌,只能从最上和最下取,然后两个人轮流取,都按照自己最优的策略,//问说第一个人对多的分值.//解题思路:记忆化搜索,状态出来就非常水,dp[fl][fr][sl][sr][flag],//表示第一堆牌上边取到fl,下面取到fr,同样sl,sr为第二堆牌,flag为第几个人在取.//如果是第一个人,dp既要尽量大,如果是第二个人,那么肯定尽量小. http://www.2cto.co

HDU 2476 String painter(字符串转变)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476 题意:给定两个长度相同的串A和B.每次操作可以将A的连续一段改变为另一个字母.求将A转换成B最少需要多少次操作? 思路:首先,我们假设没有A串,那么这就跟 BZOJ1260是一样的了,即答案为DFS(0,n-1)...但是这里有了A串就有可能使得操作次数更少.因为可能有些对应位置字母是相同的.我们设 ans[i]表示前i个字母变成一样的,那么若A[i]=B[i]则ans[i]=ans[i-1]

HDU 1078 FatMouse and Cheese(记忆化搜索DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 题目大意:一个n*n的图,每个点都有奶酪,老鼠从(0,0)开始走,每次最多只能走k步就要停下来,停下的这个位置的奶酪数只能比上一个停留的位置大,并获取其奶酪,每次只能水平或垂直走,问最多能得到的奶酪. 解题思路:记忆化搜索,这方面还是写的太少,还要看别人才会,这个就当个例子参考吧. 1 #include<cstdio> 2 #include<cstring> 3 #include

HDU 1978 How many ways(第一道记忆化搜索+DP)

How many ways Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4610    Accepted Submission(s): 2726 Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并

hdu 4597 Play Game(记忆化搜索)

题目链接:hdu 4597 Play Game 题目大意:给出两堆牌,仅仅能从最上和最下取,然后两个人轮流取,都依照自己最优的策略.问说第一个人对多的分值. 解题思路:记忆化搜索,状态出来就很水,dp[fl][fr][sl][sr][flag],表示第一堆牌上边取到fl,以下取到fr,相同sl.sr为第二堆牌,flag为第几个人在取.假设是第一个人,dp既要尽量大,假设是第二个人,那么肯定尽量小. #include <cstdio> #include <cstring> #incl

hdu1331&amp;&amp;hdu1579记忆化搜索(DP+DFS)

这两题是一模一样的``` 题意:给了一系列递推关系,但是由于这些递推很复杂,所以递推起来要花费很长的时间,所以我要编程序在有限的时间内输出答案. w(a, b, c): 如果a,b,c中有一个值小于等于0,那么w(a, b, c)的值为1 如果a,b,c中有一个值大于20,那么w(a, b, c)的值为w(20, 20, 20) 如果a<b<c,那么w(a, b, c)=w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c) 否则w(a, b, c)=w(a-

HNU OJ10086 挤挤更健康 记忆化搜索DP

挤挤更健康 Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 339, Accepted users: 216 Problem 10086 : No special judgement Problem description 用边长小于N的正方形方砖(注意,不要求所有的方砖大小相同,请看样例说明)不重叠地铺满N*N的正方形房间,最少要几块方砖. Input 第一行是一个整