codeforces 607B- Zuma(区间DP)

传送门:QAQQAQ

题意:给你一个数组,每次可以删一个连续的回文串(包括长度为1),问最少删几次

思路:挺简单的DP题,但要想清楚有难度(先看数据范围,n^3可以过)

区间DP,dp[i][j]可以有两种情况更新而来:

1.a[i]==a[j],把最外面一层挖掉,答案为dp[i+1][j-1]

2.对于所有dp[i][j],枚举中间点,把它切成两半,分别求回文串加起来

为减少更新时溢出等不必要的麻烦,我把len=1或2都特判掉了

代码:

#include<bits/stdc++.h>
using namespace std;
const int inf=(int)2e9;
 
int dp[505][505];
int n,a[505];
 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            if(i==j) dp[i][j]=1;
            else dp[i][j]=inf;
        }
    }
    for(int i=1;i<n;i++)
    {
        if(a[i]==a[i+1]) dp[i][i+1]=1;
        else dp[i][i+1]=2;
    }
    for(int len=3;len<=n;len++)
    {
        for(int i=1;i<=n-len+1;i++)
        {
            int j=i+len-1;
            if(a[i]==a[j]) dp[i][j]=dp[i+1][j-1];
            for(int k=i;k<j;k++)
            {
                dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]);
            }
        }
    }
    cout<<dp[1][n]<<endl;
}

原文地址:https://www.cnblogs.com/Forever-666/p/11173408.html

时间: 2024-07-31 07:32:57

codeforces 607B- Zuma(区间DP)的相关文章

BZOJ 1032 JSOI 2007 祖码Zuma 区间DP

题目大意:按照祖玛的玩法(随意选颜色),给出一段区间,问最少用多少个球能够把所有颜色块都消除. 思路:把输入数据按照连续的块处理,保存成颜色和数量,然后用这个来DP.我们知道,一个单独的块需要两个相同的颜色可以消去,对于这样的块f[i][i] = 2,其余的>=2个的块只需要一个,这样的块f[i][i] = 1.转移就比较简单了,按照区间DP的一般思想,最外层循环的是区间长度,中间循环的是起始位置,最后循环的是松弛变量.特殊情况是这个区间的两边是同一种颜色,多加一个转移方程. CODE: #in

Codeforces 1025D(区间dp)

容易想到设f[i][j][k]为i~j区间以k为根是否能构成bst.这样是O(n4)的.考虑将状态改为f[i][j][0/1]表示i~j区间以i-1/j+1为根能否构成bst.显然如果是i-1作为根的话i~j区间都在它的右子树,所以转移时枚举右子树的根并判断是否合法,j+1类似. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring&

Financiers Game CodeForces - 737D (博弈论,区间dp)

大意: 给定$n$元素序列, 两个人从两端轮流拿数, 每一步假设对手上次取k, 那么只能取k或k+1, 先手第一步取1或2, 直到不能拿时停止. 先手要最大化两人数字和的差, 后手要最小化, 求最后差是多少. 显然状态数是$O(n^2)$的, 直接暴力DP #include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <math.h>

[CF607B] Zuma - 区间dp

从一个序列中每次取出一个回文串,求最少取几次(取出后两端外的数会相接) 设 \(f[i][j]\) 为在闭区间 \([i,j]\) 取完所有的花费,则有 \(f[i][i]=1, f[i][i+1]=1+[a[i] \neq a[i+1]]\) 转移方程 \(f[i][j] = f[i+1][j-1], a[i]=a[j]\) \(f[i][j] = min_{k=i}^{j-1} (f[i][k]+f[k+1][j])\) #include <bits/stdc++.h> using nam

Codeforces 509F Progress Monitoring (区间dp 或 记忆化搜索)

F. Progress Monitoring time limit per test 1 second memory limit per test 256 megabytes Programming teacher Dmitry Olegovich is going to propose the following task for one of his tests for students: You are given a tree T with n vertices, specified b

Codeforces 437E The Child and Polygon(区间DP)

题目链接:Codeforces 437E The Child and Polygon 题目大意:给出一个多边形,问说有多少种分割方法,将多边形分割为多个三角形. 解题思路:首先要理解向量叉积的性质,一开始将给出的点转换成顺时针,然后用区间dp计算.dp[i][j]表示从点i到点j可以有dp[i][j]种切割方法.然后点i和点j是否可以做为切割线,要经过判断,即在i和j中选择的话点k的话,点k要在i,j的逆时针方. #include <cstdio> #include <cstring&g

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】

任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a line of nn colored squares in a row, numbered from 11 to nn f

Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)

题意:给你一组括号序列,让你进行染色,对于每个括号,有无色,红色,蓝色三种方案.染色需要满足这样的条件:互相匹配的括号,有且只有一个有颜色,相邻的括号不能颜色相同(可以同为无色),问合法的染色方案数(答案%1e9+7) 分析:根据题意能够看出是区间DP,并且状态转移的时候,依赖于左右两端的颜色,所以我们用dp[i][j][x][y]表示i到j的区间内左端颜色为x,右端颜色为y的方案数. 区间[i,j]可以由两种情况得到,一种是str[i],str[j]匹配,产生新的相匹配的括号,考虑在只有一端染