51Nod 1522 上下序列 —— 区间DP
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1522
区间DP,从大往小加;
新加入一种数有3种加法:全加左边,全加右边,一左一右;
然后判断一下加完是否满足那些条件即可;
但判断这个条件还挺复杂,一不小心就写丑了错了...
冗余错误写法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,c[][];
ll f[][][];
char ch[];
bool ck(int a,int b,int fl)
{
if(fl==)
{
for(int i=,x,y;i<=m;i++)
{
x=c[i][]; y=c[i][];
if((x==a&&y==b)||(x==b&&y==a)&&c[i][]!=)return ;
if((x==a||x==b)&&y>b&&(c[i][]!=&&c[i][]!=))return ;
if((y==a||y==b)&&x>b&&(c[i][]!=&&c[i][]!=))return ;
}
return ;
}
if(fl==)
{
for(int i=,x,y;i<=m;i++)
{
x=c[i][]; y=c[i][];
if((x==a&&y==b)||(x==b&&y==a)&&c[i][]!=)return ;
if((x==a||x==b)&&y<a&&(c[i][]!=&&c[i][]!=))return ;
if((y==a||y==b)&&x<a&&(c[i][]!=&&c[i][]!=))return ;
}
return ;
}
if(fl==)
{
for(int i=,x,y;i<=m;i++)
{
x=c[i][]; y=c[i][];
if((x==a&&y==b)||(x==b&&y==a)&&c[i][]!=)return ;
if((x==a||x==b)&&(y>a&&y<b)&&(c[i][]!=&&c[i][]!=))return ;
if((y==a||y==b)&&(x>a&&x<b)&&(c[i][]!=&&c[i][]!=))return ;
}
return ;
}
if(fl==)
{
for(int i=,x=c[i][],y=c[i][];i<=m;i++,x=c[i][],y=c[i][])
if((x==a&&y==b)||(x==b&&y==a)&&(c[i][]==||c[i][]==))return ;
return ;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d %s %d",&c[i][],&ch,&c[i][]);
if(ch[]=='=')c[i][]=;
else if(ch[]=='<'&&ch[]=='=')c[i][]=;
else if(ch[]=='>'&&ch[]=='=')c[i][]=;
else if(ch[]=='<')c[i][]=;
else if(ch[]=='>')c[i][]=;
}
for(int i=;i<*n;i++)if(ck(i,i+,))f[n][i][i+]=;
for(int i=n-;i;i--)
for(int l=;l<=*n;l++)
for(int r=l+;r<=*n;r++)
if(f[i+][l][r])
{
// printf("i=%d l=%d r=%d\n",i,l,r);
int x,y;
if(l>)
{
x=l-,y=l-;
if(ck(x,y,))f[i][x][r]+=f[i+][l][r];
// printf("f[%d][%d][%d]=%d\n",i,x,r,f[i][x][r]);
}
if(r+<=*n)
{
x=r+,y=r+;
if(ck(x,y,))f[i][l][y]+=f[i+][l][r];
// printf("f[%d][%d][%d]=%d\n",i,l,y,f[i][l][y]);
}
if(l>&&r+<=*n)
{
x=l-; y=r+;
if(ck(x,y,))f[i][x][y]+=f[i+][l][r];
// printf("f[%d][%d][%d]=%d\n",i,x,y,f[i][x][y]);
}
}
printf("%lld\n",f[][][n<<]);
return ;
}
囧
于是参考了一下TJ...
调了一小时只因把 x==b 写成 y==b ?!而且还一直没仔细看...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,c[][];
ll f[][];
char ch[];
bool ck0(int a,int b)
{
for(int i=,x=c[i][],y=c[i][];i<=m;i++,x=c[i][],y=c[i][])
if(((x==a&&y==b)||(x==b&&y==a))&&(c[i][]==||c[i][]==))return ;
return ;
}
bool ck(int l,int r,int a,int b)
{
for(int i=;i<=m;i++)
{
int x=c[i][],y=c[i][],cc=c[i][];
bool ix=(x==a||x==b),iy=(y==a||y==b);
bool kx=(x>=l&&x<=r),ky=(y>=l&&y<=r);
if(cc==&&((ix!=iy)||(kx!=ky)))return ;//=
if(cc==&&(!ky&&(ix||kx)))return ;//<
if(cc==&&(!kx&&(iy||ky)))return ;//>
if(cc==&&((ix&&!iy&&!ky)||(kx&&!ky)))return ;//<=
if(cc==&&((iy&&!ix&&!kx)||(ky&&!kx)))return ;//>=
}
return ;
}
int main()
{
scanf("%d%d",&n,&m);
bool flag=; int cnt=;
for(int i=,x,y,cc;i<=m;i++)
{
scanf("%d %s %d",&x,&ch,&y);
if(ch[]=='=')cc=;
else if(ch[]=='<'&&ch[]=='=')cc=;
else if(ch[]=='>'&&ch[]=='=')cc=;
else if(ch[]=='<')cc=;
else if(ch[]=='>')cc=;
if(x==y)
{
if(cc==||cc==)flag=;
continue;//!
}
c[++cnt][]=x; c[cnt][]=y; c[cnt][]=cc;
}
if(flag){printf("0\n"); return ;}
m=cnt;
for(int i=;i<*n;i++)if(ck0(i,i+))f[i][i+]=;
for(int l=;l<=*n;l+=)
for(int i=;i<=*n-l+;i++)
{
int j=i+l-;
if(ck(i+,j,i,i+))f[i][j]+=f[i+][j];
if(ck(i,j-,j-,j))f[i][j]+=f[i][j-];
if(ck(i+,j-,i,j))f[i][j]+=f[i+][j-];
}
printf("%lld\n",f[][*n]);
return ;
}
51Nod 1522 上下序列 —— 区间DP的更多相关文章
- $51nod\ 1522$ 上下序列 $dp$
正解:$dp$ 解题报告: 传送门$QwQ$ 一年过去了$gql$还是不咋会这题,,,好菜昂我的$NOIp$必将惨败了$kk$ 考虑从大到小枚举两个相同的数填哪儿,根据那个限制,十分显然的是这两个数必 ...
- 51nod 1522 上下序列
题目描述 现在有1到n的整数,每一种有两个.要求把他们排在一排,排成一个2*n长度的序列,排列的要求是从左到右看,先是不降,然后是不升. 特别的,也可以只由不降序列,或者不升序列构成. 例如,下面这些 ...
- 编程之美2015资格赛 题目2 : 回文字符序列 [ 区间dp ]
传送门 题目2 : 回文字符序列 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串ab ...
- 51nod 1021 石子归并 - 区间dp(经典)
题目地址:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021 经典区间dp,dp[i][j] 表示将从 i 到 j 堆 ...
- TZOJ 3295 括号序列(区间DP)
描述 给定一串字符串,只由 “[”.“]” .“(”.“)”四个字符构成.现在让你尽量少的添加括号,得到一个规则的序列. 例如:“()”.“[]”.“(())”.“([])”.“()[]”.“()[( ...
- 51nod 1021 石子归并 区间DP
1021 石子归并 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 取消关注 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆 ...
- 51Nod 1021 石子归并(区间dp经典入门)
题意: N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价.计算将N堆石子合并成一堆的最小代价. n<=100 思 ...
- 【区间DP】codevs3657 括号序列题解
题目描述 Description 我们用以下规则定义一个合法的括号序列: (1)空序列是合法的 (2)假如S是一个合法的序列,则 (S) 和[S]都是合法的 (3)假如A 和 B 都是合法的,那么AB ...
- [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)
[BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个 ...
随机推荐
- Matlab学习笔记(一)
一.MATLAB概述 (一)运行环境 命令行窗口(Command Window) 表 1-1 数据显示格式设置(e_one_1.m) 格式 实例 说明 format short 3.1416 小数点后 ...
- 洛谷 2187 小Z的笔记
[题解] DP. 设f[i]表示前i个字母,保留第i个字母,最多可以保留多少个字母:设g[i]为当前字母为i的位置对应的f的最大值. 转移方程就是f[i]=max(f[i], g[j]+1) (j与 ...
- 面试高峰期,如何应对面试官的jvm刁难,特写一篇jvm面经(第一部)
已经进入三月份,正所谓金三银四,正是一年最好的招聘期,想必我的公号粉丝们一定有不少想要跳槽的吧,哈哈,/**偷偷告诉你们其实小编也准备跳槽*/(我要加个注释,被老板知道可就完蛋了),说到面试,想必大家 ...
- 前端开发:JavaScript---DOM & BOM
DOM:Document Object Model 文档对象类型 模态框案例 <!DOCTYPE html> <html lang="en"> <h ...
- 【IntelliJ】IntelliJ IDEA的安装破解及使用
结合两位大牛CV的,写的很全面,仅供自己使用 转载地:http://www.jianshu.com/p/ad3830095fb3 https://www.cnblogs.com/kangjianwei ...
- springboot技术
一 我们为什么要用SpringBoot? 1. SpringBoot核心功能 SpringBoot的核心最足要的功能是自动配置,简单说下springBoot,springboot可以替代额xml配 ...
- SystemTap 学习笔记 - 安装篇
https://segmentfault.com/a/1190000000671438 在安装前,需要知道下自己的系统环境,我的环境如下: uname -r 2.6.18-308.el5 Linux ...
- 我的arcgis培训照片10
来自:http://www.cnblogs.com/gisoracle/p/4297439.html
- 搭建ELK收集PHP的日志
架构: filebeat --> redis -->logstash --> es --> kibana 每个客户端需要安装filebeat收集PHP日志 filebeat把收 ...
- [React] Build a slide deck with mdx-deck using Markdown + React
In this lesson we'll use mdx-deck to create a slide deck using Markdown and React. We'll look at add ...