fzoj 2170 花生的序列

 Problem 2170 花生的序列

Accept: 41    Submit: 127

Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

“我需要一个案件!!!”,没有案件卷福快疯了。花生不忍心看卷福这个样子,他决定帮卷福找点事情做。

花生拿了两个长度为N的相同的序列,序列都为WB(WBWBWB...)相间,并且由W开头。他将两个序列并在了一起,其中属于同个序列的元素相对位置不变。花生高兴的把新序列拿给卷福,要求卷福给每个元素标上1或2编号,表示这个元素是原来的第几个序列的元素。

卷福看完花生的序列,哭笑不得。“笨蛋!你难道不知道这个标号不唯一么!那你知道有多少种不同的标号方案么?”

可怜的花生给自己挖了个坑。快来帮他解决这个问题!

 Input

输入第一行包含一个整数t,表示输入组数。

每组数据第一行为一个整数N(1<=N<=3000),表示每个原序列的长度。

接下来一行为一个只包含’W’, ’B’的字符串,长度为2*N。

 Output

输出一个整数占一行,为标号的方案数。由于答案比较大,请将答案mod 1000000007。

 Sample Input

32WBWB2WWBB2BBWW

 Sample Output

240

Submit  Back  Status

这道题网络赛时做不出来。。。

回去想了一下。。和看了别人的解题报告。。突然发现别人写的可能有点简洁。

所以我就在写多一篇。。

题解:dp[i][j]代表第一个串选择了i个第二个串选择了j个有多少种可能。。

然后就有了dp[i][j] = (dp[i-1][j]+dp[i][j-1])%MOD;

代表选择到了第i+j的字符串时。。这个字符串可以放在第一个串或者第二个串。。

当然你还要判断能不能放进去。。因为wbwb要相间的。。而w只能放在奇数处。b只能放在偶输处

例如第一个串放了2个那第三个一定是放w了。。就是3是奇数。所以放的时候还要判断能不能放。

#include <iostream>
#include<cstdio>
#include <cstring>

using namespace std;
#define MOD 1000000007
int dp[3002][3002];
char ch[6003];
int main(int argc, const char * argv[])
{

    int t,i,j;
    int n;
    cin>>t;
    while(t--) {
        cin>>n;
        scanf("%s",ch+1);
          memset(dp,0,sizeof(dp));
        dp[0][0] = 1;
        for(i=0;i<=n;i++)
            for (j=0; j<=n; j++) {
                  if(i==0 && j==0) continue;
                  int sum = 0;
                  if(ch[i+j]==‘W‘) {
                        if(i&1)
                              sum = (sum+dp[i-1][j])%MOD;
                        if(j&1)
                              sum = (sum+dp[i][j-1])%MOD;

                        dp[i][j] = sum%MOD;
                  }
                  else {
                        if(i>0 && (i&1)==0)
                              sum = (sum+dp[i-1][j])%MOD;
                        if(j>0 && (j&1)==0)
                              sum = (sum+dp[i][j-1])%MOD;

                        dp[i][j] = sum%MOD;
                  }
            }
          cout<<dp[n][n]<<endl;
    }
    //std::cout << "Hello, World!\n";
    return 0;
}

其实这个代码是超内存的。。当然题目的数据其实是没3000.n最多达到1000.。所以只要将dp[1003][1003]就能过了

但是其实可以发现这个dp每一次都是对于上一行或者这一行递推的(dp[i-1][],dp[i][])

所以我们其实是可以将二维dp降到一维的

就好像01背包问题将前i件的维数去掉了。。

然后就有了。。

#include <iostream>
#include<cstdio>
#include <cstring>

using namespace std;
#define MOD 1000000007
int dp[3002];
int v[3002];
char ch[6003];
int main(int argc, const char * argv[])
{

    int t,i,j;
    int n;
    cin>>t;
    while(t--) {
        cin>>n;
        scanf("%s",ch+1);
        dp[0] = 1;
        v[0] = 1;
        for(i=0;i<=n;i++)
            for (j=0; j<=n; j++) {
                  if(i==0 && j==0) continue;
                  int sum = 0;
                  if(ch[i+j]==‘W‘) {
                        if(i&1)
                              sum = (sum+v[j])%MOD;
                        if(j&1)
                              sum = (sum+dp[j-1])%MOD;

                        v[j] = dp[j] = sum%MOD;
                  }
                  else {
                        if(i>0 && (i&1)==0)
                              sum = (sum+v[j])%MOD;
                        if(j>0 && (j&1)==0)
                              sum = (sum+dp[j-1])%MOD;

                        v[j] = dp[j] = sum%MOD;
                  }
            }
          cout<<dp[n]<<endl;
    }
    //std::cout << "Hello, World!\n";
    return 0;
}

时间虽然没优化多少。。但是空间就变成了200多k。。。

fzoj 2170 花生的序列

时间: 2024-10-07 17:17:17

fzoj 2170 花生的序列的相关文章

FOJ 2170 花生的序列 dp

marketplace是Eclipse发布的一个类似AppStore一样的插件和应用平台,可以从中安装Eclipse插件等.有些旧版本的Eclipse没有安装marketpalace. 一.   marketplace的安装 打开 Eclipse,菜单栏 Help -- Install New Software,弹出 install 窗口,在 Work with 中输入 http://download.eclipse.org/releases/indigo,等待获取插件内容.然后找到 然后 Ne

FZU 2170 花生的序列

动态规划,转移方程为 dp[i][j] = (dp[i-1][j]+dp[i][j-1])%MOD,定义还是比较裸的,讨论一下就可以了 #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define MOD 1000000007 int dp[3010],v[3010]; char str[6010]; int main() { int t,i,j; int n;

2014 Super Training #10 D 花生的序列 --DP

原题: FZU 2170 http://acm.fzu.edu.cn/problem.php?pid=2170 这题确实是当时没读懂题目,连样例都没想通,所以没做了,所以还是感觉这样散漫的做不好,有些题目明明很简单,却因为没看懂而放弃了,甚至去玩了,这样达不到太大的效果. 解法: 定义: dp[i][j]:前i个字母中有j个是属于第一个序列的标号方案种数. 则当遇到'B'时,因为要满足WB依次间歇出现,所以前面属于第一个序列的个数应该为奇数,即j&1时转移.当属于第二个序列的个数为奇数时((i-

福州大学第十一届程序设计竞赛

Problem 2167 大王叫我来巡山呐 Problem 2168 防守阵地 I 直接前缀和预处理 Problem 2169 shadow  .. Problem 2170 花生的序列 dp Problem 2171 防守阵地 II 线段树搞搞 Problem 2172 巡了南山我巡北山 http://blog.csdn.net/my_acm_dream/article/details/44507371 好题 Problem 2173 Nostop 矩阵高速幂 Problem 2174 卷福的

iOS MapKit导航及地理转码辅助类

Problem 2167 大王叫我来巡山呐 做的的第二题 呵呵 Problem 2168 防守阵地 I 做的第一题 打了下草稿 马上切了它 假设当前x=(ai)*1+(ai+1)*2+(ai+2)*3+''''+(aj)*m 下一次是(ai+1)*1+(ai+2)*2+(ai+3)*3+''''+(aj+1)*m = (ai)*1+(ai+1)*2+(ai+2)*3+''''+(aj)*m+(aj+1)*(m+1) -(ai+(ai+1)+(ai+2)+'''+(aj)+(aj+1)) 紫色的这

Android应用基础学习记录

福州大学第十一届程序设计竞赛 Contest Finished! Tag Pro.ID Problem Title Ratio(AC/Submit) 1 大王叫我来巡山呐 80.31%(261/325) 2 防守阵地 I 23.48%(193/822) 3 shadow 13.23%(97/733) 4 花生的序列 12.07%(21/174) 5 防守阵地 II 14.98%(68/454)   6 巡了南山我巡北山 0.00%(0/45) 7 Nostop 20.79%(21/101)  

FZOJ 2129 子序列个数

OJ题目:click here~~ 题目分析:设dp[ i ] 为前i个数的子序列的个数 , 下标从1开始.计算dp[ i ] .第一种情况, 如果x[ i ] 与前面的数都不相同 , 则 dp[ i ] = dp[ i - 1] + dp[ i - 1] + 1 , 即 = 都把x[ i ] 放在后面 + 都不把x[ i ]放在后面 + x[ i ] 单独成一个序列. 第二种情况,如果x[ i ] 与前面某个相同,则找到下标t , 使得x [ t ] == x[ i ] 且t与i最近.那么dp

序列管理

1.序列管理 序列管理主要实现系统用到序列生成规则的配置.主要包含序列配置.序列生产两个功能点. 2.术语说明 序列号:指序列中按步长递进的数字. 序列值:指按规则组合了 "拥有者.序列类型.序列时间.序列号" 的字符串. 重复周期:对应系统枚举SequenceCircles在重复周期内,序号不归零,一般按天.月.季.年为序号周期,也可以无周期,一直递增. 3.支持因子 名称 替换符 说明 拥有者 {{Owner}} 序列拥有者,一般不同工厂传入不同工厂代码,此因子一般不用,在实际的序

如何理解“字符串是一组由16位组成的不可变的有序序列”

疑惑点: 1.16位 2.不可变 3.有序序列 解惑: 1.16位指的是:字符串每个字符所占用的空间为16bits 比特(2 bytes);这是因为JS采用的是unicode编码,每个字符需要2个字符. 2.不可变指的是: 字符串对象一旦创建出来,便不能被更改.这可能有些难理解,但事实确实如此.你可能会认为s+='1' 只是在 s 后面增加一个元素 1 而已,但事实是: 先将 s 拷贝一份,记为 temp 在 temp 末尾加上'1' 将 s 变量指向 temp,并删去原来的s 这一特性,可以从