讲道理,其实我还不是太懂,这个题看到了两种写法

之前大概想的差不多,要这样实现呀:

常规写法,大概n……3

递归写法,稍微好理解一点

好了,接下来自从看了liuchuo的博客我要变身玛丽苏橙色了

题目链接 并不复杂,只是切木棍。。。 让我想到其实和以前的形式很像,这里给的是木棍最长1000,完全可以改到1000000000这种样子,但是我们存下来的是切点的位置,这种时候真的只要枚举一些切点就可以了

注意(1)

根据题目的特殊性分析,如果是最小的那个区间(头和尾相差是1)是不用切的,然后就会返回一个0

每次切的时候用a[i]存下来之后,每次只要用到那个差值就好了a[j]-a[i]

真方便啊!!

注意(2)

a[0]=0 a[n+1]=len ,有点像是题目里的隐含条件,但是切的时候要从头开始切,切到最后的啊!!!

核心代码(哇这个颜色好好看啊柠檬一样的!!!)

(怎么我看了这么久没人把博客写的五颜六色啊!!!!!!!!!除了柳婼同学)


int DP(int i,int j)
{if(dp[i][j]!=-1)return dp[i][j];else if(j-i==1)return dp[i][j]=0;else{int t;dp[i][j]=INF;for(int k=i+1; k<j; k++){t=DP(i,k)+DP(k,j)+a[j]-a[i];if(dp[i][j]>t)dp[i][j]=t;}return dp[i][j];}
}

哇! 我竟然10分钟A掉了,忽然开心!!!
下学期即便有大物也要好好敲代码啊!想再学好日语,顺便摸一个网工的证书过来哇嘎嘎嘎

//15:05  hope 10 minutes and I'll solve the I
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int len,n;
int a[55];
int d[55][55];
//remember too!!!!!!!!!!!!!
//-1 and 0 differs
int dp(int  i,int j){if(d[i][j]!=-1)return d[i][j];else if(i+1==j)return 0;else {int t=0x3f3f3f;//for every time of 枚举//啊,这个那个,因为我们知道1,1是没意义的,实际上1,2也是没意义的,//理论上完全可以化成0然后找意义啥的,所以没等号,有+1for(int k=i+1;k<j;k++){d[i][j]=dp(i,k)+dp(k,j)+a[j]-a[i];//因为分解开的是j和i这个状态,希望搞搞清楚t=min(t,d[i][j]);//d[i][j]=t;}d[i][j]=t;//记得最后要赋值了}return d[i][j];
}int main(){while(cin>>len,len){//good ways for judging 0 remember!//yes!  remains at least a year herecin>>n;for(int i=1;i<=n;i++)cin>>a[i];a[0]=0;a[n+1]=len;memset(d,-1,sizeof(d));//two index can use it to///------------------cout<<"The minimum cutting is "<<dp(0,1+n)<<"."<<endl;}return 0;
}

(下面的待补充,以后不是水题的用大号切或者交到洛谷(?))

括号匹配问题:

(1)n3的算法,可以化简,但不是现在

(2)我提出了一个大胆猜想:如果直接暴力做呢?

zj说会串的,比如([)]这样会判定为合法

再不济,( [ ) ] )也不能统计的

我们还是每个状态就都考虑一下比较靠谱

再说n是1000啊。。。

怎么就想不到要用区间dp来做呢。。

然后就是这里有一些数据,针对: ([()

在我最后看的那份代码里面,链接 新年抽大奖!点击试试手气(不)

做好初始化工作。和上面的不同的是-----

先枚举掉的是长度,按照每个长度会有怎么样的i和j  i是起点,j是终点,是+len得到的

随后再用O(n)的时间跑一遍,对于从i到j的这个串,从哪里切开是最好的,并且保存下来,这里要求min,就取min

反正都已经是匹配完成了的  就取最小的裂开形式哦呀  这样()[ ] 这不就这样断着匹配上了

因为最开始枚举过来的时候 () 1-2 大概就到了2 1  理所当然是0了。。 min被记住

如果是(()枚举的时候从1 3 到2 2 就是1

写法有很多。。。可以试试记忆化

枚举的话,先是枚举长度,长度小的时候,每个地方端点也很小,k那里只能枚举一次

长度很长的时候,0-4的只能枚举一个0-4的if else  之后k断点就多了,3个地方都可以分,取得一个最小的-。-

-。-   。。。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 110
#define inf 0x3f3f3f3fint dp[N][N];
char s[N];int main()
{scanf("%s", s);int n = strlen(s);for (int i = 0; i<n; ++i) dp[i][i] = 1;for (int len = 1; len<n; ++len)for (int i = 0; i + len<n; ++i){int j = i + len;// printf("i %d len  %d   j  %d  \n", i, len, j);dp[i][j] = inf;if (s[i] == '('&&s[j] == ')' || s[i] == '['&&s[j] == ']')dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);else if (s[i] == '('&&s[j] != ')' || s[i] == '['&&s[j] != ']')dp[i][j] = min(dp[i][j], dp[i + 1][j] + 1);else if (s[i] != '('&&s[j] == ')' || s[i] != '['&&s[j] == ']')dp[i][j] = min(dp[i][j], dp[i][j - 1] + 1);//printf(" dp %d\n", dp[i][j]);for (int k = i; k < j; ++k) {dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);//    printf("i %d  k %d  j  %d  dp %d\n",i, k,j,dp[i][j]);}//cout << "-----" << endl;}printf("%d\n", dp[0][n - 1]);return 0;
}

还有 ,这是codevs的代码,uva的还要路径, 我已经阵亡了

--------------------

以下为转载

最后一次把不合法的S变为合法的之前可能情况: 
1)S形如(S′)或[S′]: 
只需把S′变合法即可。 
f[i,j]= f[i+1,j-1] 
2)S形如(S′ 或[S′: 
先把S′变为合法的,右边加 )或]即可。 
f[i,j]= f[i+1,j]+1 
3)S形如 S′)或S′]: 
先把S′化为合法的,左边加(或 [即可。 
f[i,j]= f[i,j-1]+1 
4)把长度大于1的序列SiSi+1…..Sj-1Sj分为两部分: 
Si…… Sk,Sk+1….. Sj 
分别化为规则序列. 
则:f[i,j]=f[i,k]+f[k+1,j] ;i<=k<=j-1; 
上述4种情况取最小值即可。

---------------------------------------------------------------------

我们还没有解决路径输出问题:这里用到了很巧妙的方法,先常规算完了对于整个串 的,拿到一个结果,根据这个结果再算,

用print递归打印(0,n-1),如果匹配就( [             print (i,j)               ])

如果不匹配就() print 或者是print  ()

但是要煲粥保证最优,这里就更迷了,不管你那个结果是怎么形成的,只要我遍历的时候搞到他了,我就认为他是可行的

 if(dp[x][y]==dp[x][k]+dp[k+1][y]){print(x,k); print(k+1,y);return;  }

print里面还要有临街状态,,

 if(x>y) return;

emmmmm,接下来我要自己打了。(代码待补充)

还有一个问题就是gets,因为可能是空串。可谓是非常坑爹,可能一般人也想不到了

大概是说了at  most吧。。给数据的话就是0<=x<=100了,所以读入有坑。

写了个记忆化版本的,没有用fgets,也没输出路径


#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
int d[105][105];
int rec;
string s;
int dp(int i, int j) {//记忆化  一般会比递推快一点??if (d[i][j] != 0)return d[i][j];else if (i == j + 1)return 0;///  3 2else if (i == j)return 1;d[i][j] = 0x3f3f3f;if (s[i] == '('&&s[j] == ')' || s[i] == '['&&s[j] == ']')d[i][j] = min(d[i][j], dp(i + 1, j - 1));else  if (s[i] == '('&&s[j] != ')' || s[i] == '['&&s[j] != ']')d[i][j] = min(d[i][j], dp(i + 1, j) + 1);else  if (s[i] != '('&&s[j] == ')' || s[i] != '['&&s[j] == ']')d[i][j] = min(d[i][j], dp(i, j - 1) + 1);//这三种情况之后,还要分裂开讨论for (int k = i; k < j; k++) {d[i][j] = min(d[i][j], dp(i, k) + dp(k + 1, j));}//***************  k不能等于j,不然会stack overflow// 为什么呢? 1,2   的时候(1,2)+(3,2),反正会非法越界访问吧///d[i][j]先初始化成inf//k=ireturn d[i][j];
}int main() {int t; cin >> t; while (t--) {cin >> s;//这两行格式不对 后面要改的int n = s.length();for (int i = 0; i <= n; i++)d[i][i] = 1;// one can't find another//dp[i+1][j]是0   at first we have known it...rec = dp(0, n - 1);cout << rec << endl;//print(0,n-1);}return 0;
}

然后。。。 我写了两天这个题。。。zj一直劝我记忆化搜索,记忆化搜多,后来T了。。。。

后来T了。。。。。。。。

后来T了。。。。。。。。

结果zj狂笑不止。。。。。。。。。。。。。

好吧,我感觉我已经没有精力了,下面是T的代码

需要注意

①    for (int k = i; k <j; k++) {
        d[i][j] = min(d[i][j], dp(i, k) + dp(k + 1, j));     }

这里是不能等于j的,不然就会(1,2)一直循环下去

(在求1,2值的时候跑到一个这样的k,k没结果,一直跑,栈堆得很高,最后就overflow了)

②d[i][j]=inf 不然求的时候会被0 min掉值

③ 记忆化搜索大部分情况下好一点,访问的状态少(?)

但这个题访问的状态很多,都要访问,T也很多,函数开销不可避免,就又很多栈,最后T了

.......

④fgets  会把最后那个空格读进去,所以要s.len-1  (n) 否则答案不对了。还有就是s要是char数组

fgets(s,999,stdin);

最后记得多个T一定要清空


#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
typedef long long ll;
int d[105][105];
int rec;
char s[105];
//string s;
int dp(int i, int j) {//记忆化  一般会比递推快一点??//cout << i << " " << j <<" "<<d[i][j]<< endl;if (d[i][j] != 0)return d[i][j];else if (i == j + 1)return 0;///  3 2else if (i == j)return 1;d[i][j] = 0x3f3f3f;if (s[i] == '('&&s[j] == ')' || s[i] == '['&&s[j] == ']')d[i][j] = min(d[i][j], dp(i + 1, j - 1));else  if (s[i] == '('&&s[j] != ')' || s[i] == '['&&s[j] != ']')d[i][j] = min(d[i][j], dp(i + 1, j) + 1);else  if (s[i] != '('&&s[j] == ')' || s[i] != '['&&s[j] == ']')d[i][j] = min(d[i][j], dp(i, j - 1) + 1);//这三种情况之后,还要分裂开讨论for (int k = i; k <j; k++) {d[i][j] = min(d[i][j], dp(i, k) + dp(k + 1, j));}//***************  k不能等于j,不然会stack overflow// 为什么呢? 1,2   的时候(1,2)+(3,2),反正会非法越界访问吧///d[i][j]先初始化成inf//k=ireturn d[i][j];
}void print(int i, int j) {if (i > j) return;if (i == j) {if (s[i] == '(' || s[i] == ')') printf("()");else printf("[]");return;}int ans = d[i][j];if ((s[i] == '('&&s[j] == ')' || s[i] == '['&&s[j] == ']') && ans == d[i + 1][j - 1]) {printf("%c", s[i]); print(i + 1, j - 1); printf("%c", s[j]);return;}for (int k = i; k < j; k++)if (ans == d[i][k] + d[k + 1][j]) {print(i, k); print(k + 1, j);return;}//..... ???怪不得ans没报错。。。  我真是shadiao  里面也要递归啊
}int main() {int t; cin >> t;getchar();while (t--) {//getchar();fgets(s, 105, stdin);//cin >> s;//cout << s << endl;// aba  如果后面是1  就读a  如果是999  就读一堆 到换行符结束//为了应对空格。。  这是c++11的新语法int n = strlen(s)-1;for (int i = 0; i < n; i++) {for (int j = i+1; j < n; j++) {d[i][j] = 0;}}for (int i = 0; i <= n; i++)d[i][i] = 1;// one can't find another//dp[i+1][j]是0   at first we have known it...rec = dp(0, n - 1);//cout << rec << endl;print(0,n-1);cout << endl;// << endl;}return 0;
}

wzj最帅

--------------------

(不准 的不准的。。)(下面是图片)

emmmmmmm。。。 我好想做bzoj-。-

刚刚看到他们初中就开始参加noip的好多人 ,而我大二下才开始搞这个东西,大二寒假sort才刚刚知道怎么用,我真是呜呜呜呜呜呜┭┮﹏┭┮  我已经20岁了,洛谷上到处都是小孩子……

“ 算下来这已经是我参加noip的第四年了呢 ” 我&……%¥()

claris 3500题的bzoj-。-啊啊啊啊啊啊啊~

在洛谷上刷到300我觉得也已经就很厉害了……

或者是把抽特王的题单也写完……啊啊啊啊

一直做一件事情做不出来其实就挺有挫败感的……

但是摸着鱼做就……啊啊啊啊啊啊……  我们那里真是个小地方 我怎么就没早点知道这些东西呢……

【区间dp】uva10003+ uva 1626 括号匹配问题 【有空自己记忆化写一下!!!】相关推荐

  1. POJ 2955 区间DP必看的括号匹配问题,经典例题

    Brackets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14226 Accepted: 7476 Description ...

  2. 【UVA 437】The Tower of Babylon(记忆化搜索写法)

    [题目链接]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  3. UVA 1626括号序列DP

    题意: 题目背景: 我们将正规括号序列定义如下: 空序列是正规括号序列. 如果S是一个正规括号序列,那么(S)和[S]都是正规括号序列. 如果A和B都是正规括号序列,那么AB是一个正规括号序列. 例如 ...

  4. UVA 1626 括号序列

    题目描述:https://vjudge.net/problem/UVA-1626 设串S至少需要增加d(S)个括号,转移如下: 如果S形如(S′)或者[S′],转移到d(S′). 如果S至少有两个字符 ...

  5. UVA 10798 - Be wary of Roses(记忆化BFS)

    UVA 10798 - Be wary of Roses 题目链接 题意:给定一个地图,人一开始在中心,问选择一种走法走出去,使得面朝任何一个方向走,踩到的花的最大值最小 思路:用优先队列进行BFS, ...

  6. 【DP】 POJ 2955 Brackets 区间DP

    从小区间到大大区间 并计算 当前能否 括号匹配 #include <cstdio> #include <cstring> #include <cstdlib> #i ...

  7. Palindrome subsequence HDU - 4632 区间dp|记忆化搜索

    // 区间dp import java.util.Scanner;/**** @author CN*/ public class main {static int mod = 10007;static ...

  8. SDU_week16_CSP模测(T4区间dp)

    目录 T1 数鸭子 题目描述 题目分析 长长记性 代码 T2 ZJM要抵御宇宙射线 题目描述 题目分析 长长记性 代码 T4 宇宙狗的危机(区间dp) 题目描述 题目分析 代码 T1 数鸭子 题目描述 ...

  9. 【动态规划笔记】区间dp:括号匹配(删除字符和括号匹配)

    代码: //区间dp:括号匹配 #include<iostream> #include<string> #include<string.h> using names ...

最新文章

  1. 学会 IDEA REST Client后,postman就可以丢掉了...
  2. 维护服务器技术员流程,技术员岗位工作的流程表.doc
  3. 说说JavaScriptCore
  4. Starting httpd: httpd: Could not reliably determine the server's fully qualified domain name 解决
  5. 【全电发票】开票金额总额度发生了什么变化?
  6. 给页面字段中添加一个按钮,点击按钮实现弹窗效果
  7. 【水滴石穿】react-native-book
  8. 关于浏览器预检(OPTIONS)请求
  9. asp.net Code学习二(使用vs 2015 update 3)
  10. 下轮“双一流”将有高校下车?教育部最新说法来了!
  11. Java移位运算符:<<,>>,>>>
  12. 不重启linux服务器禁用U盘,如何在Linux服务器上禁用U盘?
  13. 电脑端哔哩哔哩视频下载
  14. rar、zip、7z等压缩率的测试
  15. 如何用研发效能搞垮一个团队
  16. aspx如何获取aspx.cs中定义的变量、方法;
  17. 信息安全系统设计基础期中总结
  18. win10更新后office2016图标显示空白
  19. Unity 利用HDRP《异教徒:数字人》中的眼球遮蔽方法,计算眼眶投影
  20. 1121. Damn Single (25)

热门文章

  1. Linux 的 IO 通信 以及 Reactor 线程模型浅析
  2. Dalvik和ART的区别
  3. 【植树节专题】回顾TcaplusDB的十年发展史
  4. 软件测试工程师必知试题 | 根基
  5. ENAS:通过参数共享实现高效的神经架构搜索《EfficientNet Neural Architecture Search via Parameter Sharing》
  6. 双系统安装红旗linux,win7与红旗Linux7.0双系统安装的方法
  7. 用matlab实现数字水印,应用MATLAB实现数字水印算法(1)
  8. (转载)VoLTE简介
  9. OpenWrt21 EC20 R2.0驱动添加
  10. jmeter高并发测试_利用Apache JMeter进行高并发测试(二)