当前位置: 首页 > news >正文

区间 dp 系列 题解

1.洛谷 P4342 IOI1998 Polygon

我的博客

2.洛谷 P4290 HAOI2008 玩具取名

题意

某人有一套玩具,并想法给玩具命名。首先他选择 W, I, N, G 四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用 W, I, N, G 中任意两个字母代替,使得自己的名字能够扩充得很长。

现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。

四个整数 W , I , N , G W, I, N, G W,I,N,G,表示每一个字母能由几种两个字母所替代:

  • 接下来 W W W 行,每行两个字母,表示 W 可以用这两个字母替代。

  • 接下来 I I I 行,每行两个字母,表示 I 可以用这两个字母替代。

  • 接下来 N N N 行,每行两个字母,表示 N 可以用这两个字母替代。

  • 接下来 G G G 行,每行两个字母,表示 G 可以用这两个字母替代。

  • 最后一行一个长度不超过 L L L 的字符串。表示这个玩具的名字。

一行字符串,输出该名字可能由哪一个字母变形而得到。(按照 W, I, N, G 的顺序输出)

如果给的名字不能由任何一个字母变形而得到则输出 The name is wrong!

L ≤ 200 L \leq 200 L200 W , I , N , G ≤ 16 W, I, N, G \leq 16 W,I,N,G16

思路

其实就是原字符串中,找其中两个合并成特定的一个字母,问最后能否变成只有一个字母。合并问题,想到用区间 dp。

不妨给 4 4 4 个字母编号: W , I , N , G \rm W,I,N,G W,I,N,G 分别对应 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4。设 f i , j , x f_{i,j,x} fi,j,x 表示区间 [ i , j ] [i,j] [i,j] 的字符,是否可以合并成编号为 x x x 的字符。

考虑转化为子问题:将区间 [ i , j ] [i,j] [i,j] 拆分成 [ i , k ] [i,k] [i,k] [ k + 1 , j ] [k+1,j] [k+1,j],并且分别期望用编号为 p q , p , q pq,p,q pq,p,q 的字母来覆盖(这变量够直观吧)。

如果左右区间都可以被完全替换为期望字符,并且编号为 p q pq pq 的字母可以被两个编号分别为 p , q p,q p,q 的字母并起来替代,那么 f i , j , x = 1 f_{i,j,x}=1 fi,j,x=1

至于关系就很好处理了。我的代码是懒人写法:

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=203;
ll m[5];
string s;
bool vis[5][5][5],f[N][N][5];//f(i,j,x):区间[i,j]能否替换成字母编号x 
ll chg(char c)
{
	if(c=='W')return 1;
	if(c=='I')return 2;
	if(c=='N')return 3;
	return 4;
}
char print(ll i)
{
	if(i==1)return 'W';
	if(i==2)return 'I';
	if(i==3)return 'N';
	return 'G';
}
int main()
{
	ios::sync_with_stdio(0);
	for(int i=1;i<=4;i++)
	cin>>m[i];
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=m[i];j++)
		{
			string t;
			cin>>t;
			vis[i][chg(t[0])][chg(t[1])]=1;
		}
	}
	cin>>s;
	ll n=s.size();
	s='*'+s;
	for(int i=1;i<=n;i++)
	f[i][i][chg(s[i])]=1;
	for(int len=2;len<=n;len++)
	{
		for(int i=1;i+len-1<=n;i++)
		{
			ll j=i+len-1;
			for(int k=i;k<j;k++)
			for(int pq=1;pq<=4;pq++)
			for(int p=1;p<=4;p++)
			for(int q=1;q<=4;q++)
			if(vis[pq][p][q]&&f[i][k][p]&&f[k+1][j][q])f[i][j][pq]=1;
		}
	}
	bool flag=0;
	for(int pq=1;pq<=4;pq++)
	{
		if(f[1][n][pq])cout<<print(pq);
		flag|=f[1][n][pq];
	}
	if(!flag)puts("The name is wrong!");
	return 0;
}

3.CF607B Zuma

题意

Genos \texttt{Genos} Genos 最近在他的手机上下载了祖玛游戏。在祖玛游戏里,存在 n n n 个一行的宝石,第 i i i 个宝石的颜色是 a i a_i ai。这个游戏的目标是尽快的消灭一行中所有的宝石。

在一秒钟, Genos \texttt{Genos} Genos 能很快的挑选出这些有颜色的宝石中的一个回文的、连续的子串,并将这个子串移除。每当一个子串被删除后,剩余的宝石将连接在一起,形成一个新的行列。

求把整个宝石串都移除的最短时间。

1 ≤ n ≤ 500 1 \le n \le 500 1n500

思路

合并就考虑区间 dp,设 f i , j f_{i,j} fi,j 表示区间 [ i , j ] [i,j] [i,j] 能否被完全消除,那么有几个明显的结论:

  • f i , i = 1 f_{i,i}=1 fi,i=1
  • f i , i + 1 = { 1 , a i = a i + 1 2 , a i ≠ a i + 1 f_{i,i+1}=\left\{\begin{matrix} 1,a_i=a_{i+1}\\ 2,a_i\neq a_{i+1} \end{matrix}\right. fi,i+1={1,ai=ai+12,ai=ai+1
  • f i , j = f i + 1 , j − 1 , a i = a j f_{i,j}=f_{i+1,j-1},a_i=a_j fi,j=fi+1,j1,ai=aj

前两点用于初始化。第三点作为特殊情况;对于朴素情况,枚举断点 k ∈ [ i , j ) k\in[i,j) k[i,j) 就好:
f i , j = min ⁡ { f i , k + f k + 1 , j } f_{i,j}=\min\{f_{i,k}+f_{k+1,j}\} fi,j=min{fi,k+fk+1,j}

只需讨论区间长度为 3 3 3 的就好了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=502,inf=0x3f3f3f3f;
ll n,a[N];
ll f[N][N];//f(i,j):区间[i,j]全部消除的最短时间 
bool palin(ll l,ll r)
{
	for(int i=l,j=r;i<=j;i++,j--)
	if(a[i]!=a[j])return 0;
	return 1;
}
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++)
	{
		f[i][i]=1;
		if(a[i]==a[i+1])f[i][i+1]=1;
		else f[i][i+1]=2;
		for(int j=i+2;j<=n;j++)
		f[i][j]=inf;
	}
	for(int len=3;len<=n;len++)
	{
		for(int i=1;i+len-1<=n;i++)
		{
			ll j=i+len-1;
			if(a[i]==a[j])f[i][j]=f[i+1][j-1];
			for(int k=i;k<j;k++)
			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
		}
	}
	printf("%lld",f[1][n]);
	return 0;
}

相关文章:

  • 《深入探秘:分布式软总线自发现、自组网技术原理》
  • 部署大模型不再难:DeepSeek + 腾讯云 HAI 实战教程
  • Java 列表初始化全解析:7种方式详解与最佳实践
  • SpringBoot和微服务学习记录Day2
  • python基础语法10-异常处理
  • TPS入门DAY03 服务器篇
  • 提示词工程
  • 牛客KY257 日期累加
  • 逆向工程的多层次解析:从实现到领域的全面视角
  • Spark核心知识总结
  • 2025年汽车加气站操作工证考试内容
  • html元素转图像之深入探索 html - to - image:功能、应用与实践
  • 探索原生JS的力量:自定义实现类似于React的useState功能
  • popupwindow拦截返回点击
  • 学习笔记083——Java Stream API
  • 第七天 开始Unity Shader的学习之Unity中的基础光照之高光反射光照模型
  • S7-1200 PLC热电偶和热电阻模拟量模块
  • java基础-修饰符
  • Jakarta EE 11发布:云原生Java企业应用的新标准
  • Android Studio Narwhal | 2025.1.1新功能
  • 哪个网站做任务可以赚钱/百度售后电话人工服务
  • h5网站开发公司/冯耀宗seo视频教程
  • 建立相适应的政府债务管理机制/seo快速排名是什么
  • 通过社交网站来做招聘决定/html简单网页成品
  • 怎么给网站做seo优化/广点通投放平台登录
  • 银川网站设计公司/seo排名点击软件运营