Water problem zoj(2800) soj(1083) 区间动态规划

题目描述

 https://oj.yukisaki.cn/problem?problem_id=1083

 

据说大主任认识一个自认为很聪明的人。

有一天,大主任问那个人:

“你能告诉我一个集合的表示法么?”

“当然,我这么聪明!”他回答说,“那是一组在两个大括号包围的元素,但括号里也可以为空。这些元素可以是一个新的集合,也可以是一个字母,他们之间用‘,’隔开。”

“那么。”大主任说,“如果我给你一个表示,你能告诉我它是一个正确的集合吗?”

“当然,我这么聪明!”他又回答说,“傻瓜都会做。”

“很好”大主任想,“这样我就可以证明他是傻瓜了!”

现在大主任准备用这样一道题来虐掉那个人。你将得到下列规定:

集合:“{” 元素列表 “}”

元素列表:空 or 元素子列表

元素子列表:元素 or 元素“,”元素子列表

元素:子元素 or 集合

子元素:“{” or “,” or“}”

注意:“空”,表示没有任何成分,并不是有一个表示“空”的字符。

大主任觉得这题太水了,他不屑于写标程,倒是给出了一大堆邪恶的数据。为了帮助大主任证明那个人是傻瓜,作为大主任下手的你也就难逃帮他写标程的厄运了。请你写一个程序判断一个表达式是否是满足上述规定的集合。

 

输入格式

 

本题有多组数据。

输入的第一行为数据组数T。

第2到T+1行,每行给出一个字符串。

 

输出格式

 

共T行。

按下列格式输出:

若是一个满足规定的集合,则输出:“Word #数据组号: Set”

若不是,则输出:“Word #数据组号: No Set”

 

样例输入

 

4
{}
{{}}
{{}},{,}}
{,,}

 

样例输出

 

Word #1: Set
Word #2: Set
Word #3: Set
Word #4: No Set

 

数据范围

 

对于40%数据,字符串长度不超过6;

对于100%数据,字符串长度不超过200,T<=1000。

 

 

此题最明显的做法就是直接按照题目要求写四个函数然后递归调用,并用一个数组记录下已经调用过的结果。

但是最近新学了一种大佬的解法:

即: 空间dp

此题我WA了无数遍

中心思想是使用 数组dp[maxn][maxn] 记录下区间[ i , j ] 是否满足条件;

根据上述集合的定义我们可以推出主要满足以下俩个充分不必要条件

 

1、若区间 [i+1 , j-1] 是满足条件的,并且s[i]=='{'   s[j]=='}',则区间 [i,j] 满足条件;

2、若区间中有某个位置是‘,’,则判断 [i,k-1]&&[k+1,j] 是否满足条件,若满足,则该区间【i,j】满足条件。

 

于是我们可以使用 |= 运算符表示充分不必要条件

时间复杂度应该是O(n^3)?

空间复杂度是O(N^2)

下面是代码

#include <iostream>
#include<cstring>
#define maxn 250
using namespace std;
int dp[maxn][maxn];
char s[maxn];
bool is_set(int l,int r){
  int len=r-l+1;
  if(len==2)return s[l]=='{'&&s[r]=='}';
  for(int i=l;i<r;++i){
    if(s[i]=='{'&&s[i+1]=='}')dp[i][i+1]=1;//单独的元素
    dp[i][i]=1;
  }
  dp[r][r]=1;
  for(register int mark=3;mark<=len;++mark){
  for(int i=l;i<len-mark+1;++i)
{   
int j=i+mark-1;   if(s[i]=='{'&&s[j]=='}')dp[i][j]|=dp[i+1][j-1];   for(int k=i+1;k<j;++k){     if(s[k]==',')dp[i][j]|=dp[i][k-1]&dp[k+1][j];       }     } }   if(s[l]=='{'&&s[r]=='}')return dp[l+1][r-1];   else return false; } int main() {   long int T;   scanf("%d",&T);   for(register int i=1;i<=T;++i){   scanf("%s",s);   memset(dp,0,sizeof(dp));   if(is_set(0,strlen(s)-1))printf("Word #%d: Set\n",i);   else printf("Word #%d: No Set\n",i);   } return 0; }

 

注:28行是dp[l+1][r-1] 不是的dp[l][r],具体原因大概是对于‘,’的检测在后面而不是在前面

 

posted @ 2021-03-12 11:23  ୧⍤⃝୨  阅读(85)  评论(0)    收藏  举报