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.( )是一个 ...
随机推荐
- 1001. A+B Format (20) (%0nd)
1001. A+B Format (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Calculate ...
- <<编程之美>> -- 队列中取最大值操作的问题
不得不说编程之美是一本好书,虽然很多题目在做acm中的过程中遇到过,不过还是有很多值得思考的地方 这是今天在编程之美上看到的一个问题,对于栈转化成队列的一个思考 平时都太过依赖c++内函数库中的栈和队 ...
- codeforces Gym 100735 D、E、G、H、I
http://codeforces.com/gym/100735 D题 直接暴力枚举 感觉这道题数据有点问题 为什么要先排下序才能过?不懂.. #include <stdio.h> #in ...
- POJ 3169_Layout
大早上水一发=.= 题意: n头牛按编号顺序站成一列,给定n头牛之间的位置关系,求出第n头牛和第一头牛之间的最大距离. 分析: 差分约束系统,这题不等式关系还是挺好找的.注意因为按照顺序排列,所以有d ...
- Codeforces 777E(离散化+dp+树状数组或线段树维护最大值)
E. Hanoi Factory time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案
Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec 题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度. 注释:$1\le n\le 2\cdot 1 ...
- POJ2632 Crashing Robots 解题报告
Description In a modernized warehouse, robots are used to fetch the goods. Careful planning is neede ...
- P1165 日志分析 洛谷
https://www.luogu.org/problem/show?pid=1165 题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况 ...
- HTML5 全屏化操作功能
由于项目中用到了全屏化挫折功能,查看了API后写了一个简单的全屏化model <!DOCTYPE html> <html> <head> <meta http ...
- 多路转接模型之poll
poll系统调用和select类似.也是在指定时间内轮询一定数量的文件描写叙述符,以測试当中是否有就绪者.poll和select效率差点儿相同,仅仅是其使用接口相对简单些,poll不在局限于1024个 ...