[NOIP模拟][审题][数据结构][bfs/dp]
来源:互联网 发布:网络测试工具包 编辑:程序博客网 时间:2024/05/21 22:46
NOIP 模拟赛
T1:Mushroom 的序列
【问题描述】 Mushroom 手中有 n 个数排成一排,现在 Mushroom 想取一个连续的子序列,使得这个 子序列满足:最多只改变一个数,使得这个连续的子序列是严格上升子序列,Mushroom 想 知道这个序列的最长长度是多少。
【输入格式】 第一行一个整数 n,表示有 n 个数。 第二行为 n 个数。
【输出格式】 一个数,为最长长度。
【输入样例】 6 7 2 3 1 5 6
【输出样例】 5
【样例解释】 选择第 2 个数到第 6 个数,把 1 改变成 4 即可。
【数据范围】 对于 30%的数据,n<=10 对于 60%的数据,n<=1000 对于 100%的数据,n<=100000
【解题思路】
连续二字很重要,,,所有这个和LIS完全没有关系,,
左边右两边同时扫一遍,预处理,然后枚举那个需要改变的点,这时有两种情况,如果a[i-1]-a[i-2]>=2那么这个答案即为左右两边的序列加这个点的最大值,如果不是这种情况,只能考虑单边。。。QAQ读错题
#include<iostream>#include<cstdio>#include<cmath>using namespace std;const int N=100050;int a[N],b[N],c[N],n;int main(){ freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); scanf("%d",&n); for(int i = 1; i <=n; i++) scanf("%d",&a[i]); b[1]=1; for(int i = 2; i<= n; i++) if(a[i]>a[i-1])b[i]=b[i-1]+1; else b[i]=1; c[n]=1; for(int i=n-1;i>=1;i--) if(a[i]<a[i+1])c[i]=c[i+1]+1; else c[i]=1; int ans=1; for(int i = 1; i<= n; i++){ if(a[i+1]-a[i-1]>=2) ans=max(ans,b[i-1]+c[i+1]+1); ans=max(ans,b[i-1]); ans=max(ans,c[i+1]); } cout<<ans<<endl; return 0;}
T2:Mushroom 的区间
【题目描述】 Mushroom 有一行数,初始时全部是 0。现在 Mushroom 有 m 个区间[L,R],他希望用以 下操作得到新的序列。 从 m 个给定区间中选择一个区间[s,t],把区间中的数对应元素全部翻转。(0 变 1,1 变 0) 请告诉 Mushroom 他能得到多少区间。(模 10^9+7)
【输入格式】 第一行包含两个整数 n,m。表示 n 个数和 m 个区间。 接下来 m 行是所表示的区间。
【输出格式】 一个整数,表示能得到的区间数。
【样例输入】 3 3 1 1 2 2 3 3
【样例输出】 8
【数据范围】 对于 30%的数据,n,m<=20 对于 60%的数据,n,m<=100 对于 100%的数,n,m<=100000
【样例解释】 每个位置都可以单个修改,所以有 8 种可能。
【解题思路】
很巧妙,,,这道题。
比如一个区间1___2___3___4___5___6
另一个区间1__2__3,还有一个区间3__4__5__6
那么可以得知这三个区间可以只用两个区间,无论那两个(注:不一定要两个小的),,任何两个都可以表示出。
再像1—2—3—4—5—6
1—2—3—4
3—4—5—6
3—4
同理上面任意3个都可以包含四个的这种情况。
所以这两种情况的价值区间个数是要–的,
这种可以dfs,搜索,记录vis,
然而并查集这个优美的东东更是特别好。
一个操作,,起点s,终点t,这两个点,把fa[t]==s;
那么相当于一个点的父亲即使这个操作的起点,,这样,对于上述的两种特殊情况,当处理最后一个区间的,发现他的起点终点都是一个fa,所以这个区间无价值。。
最后算出来的有价值区间为k个,那么,方案数目为2^k,因为每个区间有取与不取的情况。。。(这个地方自己竟然没想到==)。。
欸,风萧萧兮易水寒,,,,为何我没有想到,还是自己太蒟蒻了。。。。。。。。
#include<iostream>#include<cstring>#include<cstdio>#define FROP "seg"using namespace std;const int N=100050;int n,m,fa[N];int find(int x){ return (x==fa[x])?x:fa[x]=find(fa[x]);}const int mod=1e9+7;int kmi(int x){ if(x==0)return 1; if(x==1)return 2; int p=kmi(x/2)%mod; if(x%2)return ((long long)p*p)*2%mod; return (long long)p*p%mod;}int main(){ freopen(FROP".in","r",stdin); freopen(FROP".out","w",stdout); scanf("%d%d",&n,&m); int ans=1; for(int i = 1; i <= n; i++) fa[i]=i; for(int i = 1; i <= m; i++){ int a,b; scanf("%d%d",&a,&b); int x=find(a),y=find(b+1); if(x^y){ fa[x]=y; ans=(long long)ans*2%mod; } } printf("%d",ans); return 0;}
T3:来自风平浪静的明天
【题目描述】 冬眠了五年,光终于从梦中醒来。 千咲、要,大家都在。 隐约记得“昨天”的海船祭,爱花意外成为贡女,沉入海底。 海面冰封,却有丝丝暖流在冰面之下涌动。 此时,爱花沉睡在祭海女神的墓地。她的胞衣在一点点脱落,化作一簇簇暖流,夹杂着她的 感情,向海面上涌去。 爱花,你在哪里?
五年之后,纺已经成为海洋学研究科的大学生。 在纺的帮助下,光得知了海面下海流的情况。 纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。 纺帮你绘制了一张海流情况图,长度为 N,宽度为 M。 海很大,一边有沙滩,一边一望无际,但长度和宽度都不会超过 300。沙滩是金黄色的,所 以用 Y 表示。海是蓝色的,所以用 B 表示。暖流很暖和,所以用 H 表示 海中有大大小小的石头。石头很危险,所以用 X 表示 光相信自己一定能找到爱花(爱花的位置只有一种可能) 【输入格式】 第一行包括两个整数 N,M。 接下来 N 行,每行 M 个字符。 【输出格式】 仅一行,表示爱花的位置(如果你无能为力,请输出 -1 ,只要你尽力,光不会责怪你)
【样例输入】
5 5
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB
【样例输出】 2 3
【数据范围】 对于 30%的数据,n,m<=10 对于 70%的数据,n,m<=100 对于 100%的数据,n,m<=300
【样例解释】 在(2,3)出现第一个 H 后,经过 3s 后,出现样例输入的地图。
【题目思路】
可以bfs,这里不用dfs,因为很难判时间,,用bfs,这样一层也就是一个时间,,所以这里处理的很好,当一层放进去后加一个标志,q.push(-1),当q.front()==-1时,说明这一层已经扫完,然后再看是否已经扫完所有的‘H’
也可以用dp,没看,这里贴出来就好了。。。
哦,还有,用bfs 需要自己写队列,不然会超时一组。。。。
#include<iostream>#include<cstdio>#include<ctime>#include<cstring>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<cstdlib>#include<queue>#include<vector>#ifdef WIN32#define AUTO "%I64d"#else #define AUTO "%lld"#endifusing namespace std;#define FROP "calm"const int N = 305;#define cle(x) memset(x,0,sizeof(x))int n,m,up,down,li,ri;char a[N][N];int b[N][N],T,anx,any,tot,num;bool bo[N][N];const int con[2][4]={-1,1,0,0,0,0,-1,1};const char ch[3]={'H','B','x'};void init(){ getchar(); up=n,down=1,li=m,ri=1; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ a[i][j]=getchar(); if(a[i][j]=='H')num++; } getchar(); }}int qx[N*N],qy[N*N];bool bfs(int x,int y){ cle(qx); cle(qy); cle(bo); int head=1,tail=1; qx[tail]=x; qy[tail++]=y; qx[tail]=-1; qy[tail]=-1; bo[x][y]=true; int tt=num-1; while(head<=tail){ int xx=qx[head],yy=qy[head]; head++; if(xx!=-1){ for(int i = 0; i<4; i++){ int x1=xx+con[0][i],y1=yy+con[1][i]; if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&!bo[x1][y1]){ bo[x1][y1]=true; if(a[x1][y1]=='B')return false; if(a[x1][y1]=='H'){tt--;qx[++tail]=x1;qy[tail]=y1;} } } } else { qx[++tail]=-1; qy[tail]=-1; if(tt==0)return true; } }}int main(){ freopen(FROP".in","r",stdin); freopen(FROP".out","w",stdout); scanf("%d%d",&n,&m); init(); for(int i = 1;i<=n;i++) for(int j = 1;j<=m;j++)if(a[i][j]=='H'){ if(bfs(i,j)){ printf("%d %d",i,j); exit(0); } } cout<<"-1"<<endl; return 0;}
Flow[TIME][X][Y]表示暖流的初始位置是(X,Y),经过时间 TIME 以后,形成的图案会不会和海 流图不相符(不应是 H 的地方出现了 H 则不相符,应出现 H 的地方没有出现 H 认为相符)
YYYHB YYHHH YHHXB BBHBB BBBBB
海流图 YYYBB YYHHB YBHXB BBBBB BBBBB
相符的图(蓝色部分应该出现 H 但没有出现) YYYHH YYHHH YHHXH BHHHB BBHBB
不相符的图(红色部分不该出现 H 但出现了)
F[TIME][X][Y]=F[TIME-1][X-1][Y]&&F[TIME-1][X][Y-1]&&F[TIME-1][X+1][Y]&&F[TIME-1][X][Y+1]
记忆化 DP 时间复杂度 O(N^3) 空间复杂度 O(N^3)
找到最大的 TIME,对应的 X 和 Y 就是爱花的位置。 因为光相信自己一定能找到爱花,所以爱花的位置确定(不会有两个位置满足条件) 。
- [NOIP模拟][审题][数据结构][bfs/dp]
- [NOIP模拟][bfs][dp][CSD][表达式的计算]
- [NOIP 模拟]潜水员 DP
- 【NOIp模拟】【dp】俄罗斯方块
- [NOIP模拟题][DFS][DP]
- NOIP模拟题[dfs][DP]
- [NOIP模拟][状压DP]乘积
- NOIP模拟 探险 【树形dp】
- [NOIP模拟][数据结构][二分]Work
- [NOIP模拟]BOX(推箱子)-BFS
- [NOIP模拟题][模拟][DP][乱搞]
- NOIP模拟题 [模拟][DP][线段树]
- [noip]刘翔!加油!(审题细心问题 !!)
- 审题
- NOIP模拟题 LGTB 玩THD [DP]
- [noip模拟赛]祖先(dp)
- [noip模拟赛]二进制(dp)
- [noip模拟赛]敲砖块(dp)
- DAY92_IDALINK SERVER
- poj2516——Minimum Cost(最小费用最大流)
- Java判断一个字符串里面是否含有中文字符
- 最适合新手看的Eclipse搭建Tomcat开发环境
- Android Service完全解析,关于服务你所需知道的一切(下)
- [NOIP模拟][审题][数据结构][bfs/dp]
- unity3D新版动画如何实现动画的融合
- for——生成新闻
- 默认参数的构造函数
- Yii基础学习
- [LeetCode]Unique Paths II
- Android Retrofit 2.0 配置OkHttpClient
- 工作第十五周:上线前的惊悚
- 机械硬盘与固态硬盘的区别