P1371 NOI元丹
luogu月赛的题
本来想爆搜,但是经过ly大佬的点拨,明白这是一个dp。
我们定义dp[n]为从n开始的可行串的数目,具体如下:如果n为‘I',则是从n开始有多少个I,如果n为'O',既是从n开始有多少个’OI‘,如果n为’N‘,则是从n开始有多少个’NOI'
我们已经定义了状态,那么怎么转移呢?我们以n是‘N'为例,’NOI'的数目可以分为两部分:1)包括n, 2)不包括n。所以,我们可以这样计算dp[n],找到从n开始的第一个N和O,把两个字符的dp值相加,就得到了答案。
我们从后往前推,可以估算一下复杂度:状态数O(n),转移O(n),总的复杂度是O(n^2)。
对于每一个字串,我们都可以计算出其结果。所以下面的问题就是怎么去插。
首先,我们可以用链表来存储这一个字串,来优化一下常数;
第二,我们可以证明,对于N,把他插到最前面,一定是最优的,对于I,把他插到最后面,一定是最优的,
但是对于O我们还没有想出比较好的插法,目前的想法是去枚举。
这样在O(n2)的时间内,我们就可以算出。
ly大佬用这个算法得了60分。。。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
int n;
string str;
int cnt;
int table[maxn];
int ans[maxn];
int tmp[maxn];
//==============
int value[maxn];
int count() {
int pos = n - 1;
int i, j;
if(tmp[n] == 2) value[n] = 1;
else value[n] = 0;
while(pos != -1) {
if(tmp[pos] == 2) {
for(i = pos+1; i <= n; i++) {
if(tmp[i] == tmp[pos]) break;
}
value[pos] = value[i] + 1;
}
else if(tmp[pos] == 1) {
for(i = pos+1; i <= n; i++) {
if(tmp[i] == 1) break;
}
for(j = pos+1; j <= n; j++) {
if(tmp[j] == 2) break;
}
value[pos] = value[i] + value[j];
}
else if(tmp[pos] == 0) {
for(i = pos+1; i <= n; i++) {
if(tmp[i] == 1) break;
}
for(j = pos+1; j <= n; j++) {
if(tmp[j] == 0) break;
}
value[pos] = value[i] + value[j];
}
pos--;
}
for(i = 0; i < n; i++) {
if(tmp[i] == 0) break;
}
return value[i];
}
//==============
int main(int argc, char const *argv[])
{
cin >> n >> str;
memset(value, 0, sizeof(value));
for(int i = 0; i <= n;i++) {
if(str[i] == 'N') table[i] = 0;
else if(str[i] == 'O') table[i] = 1;
else if(str[i] == 'I') table[i] = 2;
}
tmp[0] = 0;
for(int i = 1; i <= n+1;i++) tmp[i] = table[i-1];
int a = count();
for(int i = 1; i <= n+1;i++) tmp[i] = table[i];
tmp[n+1] = 2;
int b = count();
int i, k;
for(k = n; k >= 0; k--) if(table[k] == '1') break;
for(i = 0;i <= k; i++) {
tmp[i] = table[i];
}
tmp[i] = 1;
for(;i<=n;i++) {
tmp[k] = table[k-1];
}
int c = count();
cout << max(max(a, b), c);
return 0;
}
/*void dfs(int choose, int pos) {
if(choose == n){
cnt++;return;}
if(pos == str.size()) return;
for(int i = pos; i <= str.size(); i++) {
if(tmp[i] == choose) {
ans[choose] = i;
dfs(choose + 1, i+1);}
}
}
int count() {
cnt = 0;
dfs(0, 0);
return cnt;
}*/
/*cin >> n >> str;
int maxx = 0;
for(int i = 0; i <= str.size();i++) {
if(str[i] == 'N') table[i] = 0;
else if(str[i] == 'O') table[i] = 1;
else if(str[i] == 'I') table[i] = 2;
}
int k;
for(int i = 0; i < 3; i++) {
for(int j = 0; j <= n; j++) {
for(k = 0; k <= j; k++) {
tmp[k] = table[k];
}
tmp[k] = i;
for(;k<=n;k++) {
tmp[k] = table[k-1];
}
maxx = max(maxx, count());
}
}
cout << maxx;*/
54 NONOONIONIINIOOONONIIIINNONOINOONNOOIIOIOIOIINONNNIOON
10 ONNINNONNI
P1371 NOI元丹的更多相关文章
- 洛谷P1371 NOI元丹
P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交 讨论 题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...
- 洛谷10月月赛Round.3
Rank11:260=60+100+100 P2409 Y的积木 题目背景 Y是个大建筑师,他总能用最简单的积木拼出最有创意的造型. 题目描述 Y手上有n盒积木,每个积木有个重量.现在他想从每盒积木中 ...
- 从一道NOI练习题说递推和递归
一.递推: 所谓递推,简单理解就是推导数列的通项公式.先举一个简单的例子(另一个NOI练习题,但不是这次要解的问题): 楼梯有n(100 > n > 0)阶台阶,上楼时可以一步上1阶,也可 ...
- NOI 动态规划题集
noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...
- noi 6047 分蛋糕
题目链接:http://noi.openjudge.cn/ch0405/6047/ 和Uva1629很类似,不过,可能用记忆化难写一点,状态初始化懒得搞了.就用循环好了. 状态描叙也可以修改,那个题目 ...
- NOI 2015 荷马史诗【BZOJ 4198】k叉Huffman树
抱歉因为NOIP集训,好长时间没再写题解了. NOI 2015也就只有这道题一看就能懂了-- 4198: [Noi2015]荷马史诗 Time Limit: 10 Sec Memory Limit: ...
- noi题库(noi.openjudge.cn) 1.7编程基础之字符串T31——T35
T31 字符串P型编码 描述 给定一个完全由数字字符('0','1','2',-,'9')构成的字符串str,请写出str的p型编码串.例如:字符串122344111可被描述为"1个1.2个 ...
- NOI WC2016滚粗记
Day-4 报到日,今年居然没有发包QAQ,中午到的,志愿者很热情,食堂吃不了(也有可能是吃不惯),空调打不热,有拖线板(好评),有wifi覆盖(虽然听说连上要看脸)(反正我是没连过,用的自己的流量) ...
- NOI题库刷题日志 (贪心篇题解)
这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制: 1000ms 内存限制: 65536kB 描述 在一个平面上,如果有两个点( ...
随机推荐
- flume与Mosquitto的集成
文章来自:http://www.cnblogs.com/hark0623/p/4173714.html 转发请注明 因业务需求,需要flume收集MQTT(Mosquitto)的数据. 方法就是 ...
- Spring的bean标签
Spring框架中主要有四种标签bean.alias.import.beans,其中bean标签是其他标签的基础. 一.bean标签的属性 scope:用来配置spring bean的作用域 sing ...
- BZOJ3651 : 网络通信
同[ZJOI2012]网络,把每个点拆成C个点然后用LCT维护. #include<cstdio> #include<map> #define P make_pair #def ...
- [转]C++设计模式:Builder模式
Builder模式要解决的问题是,当我们要创建很复杂的对象时,有时候需要将复杂对象的创建过程和这个对象的表示分离开来.由于在每一步的构造过程中可以映入不同参数,所以步骤相同但是最后的对象却不一样.也就 ...
- HDU 4669 Mutiples on a circle(环状DP)
题目链接 这是最早看懂题意的一题,状态转移,挺好想..但是比赛时候,就是没有想到怎么去重,而且当时有些情况,也没注意到. 先预处理的dp[0]的情况,就是以p[0]为结尾的情况.之后D就行了,例如样例 ...
- Nginx 伪静态教程
1.将多个域名指向同一web目录: server_name www.php100.com php100.com; rewrite ^/$ / redirect; 2.将不带www的域名301转向到带w ...
- java向图片上写字,两个图片合并的方法
package writeimg; import javax.imageio.ImageIO; import java.awt.Color; import java.awt.Font; import ...
- ajax无刷新获取php后台数据
$.ajax({ url:"result.php", //data:{"page":i}, dataType:"json", beforeS ...
- PDO常用方法及其应用
PDO::query() 主要是用于有记录结果返回的操作,特别是SELECT操作 PDO::exec() 主要是针对没有结果集合返回的操作,如INSERT.UPDATE等操作 PDO::prepare ...
- [GE]手动截取当前活动窗口,并且按规则命名(1/2)
Function Take-ScreenShot { <# .SYNOPSIS Used to take a screenshot of the desktop or the active wi ...