[NOIP模拟][审题][数据结构][bfs/dp]
2016-10-31 19:42
183 查看
NOIP 模拟赛
【输入格式】 第一行一个整数 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读错题
【输入格式】 第一行包含两个整数 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,因为每个区间有取与不取的情况。。。(这个地方自己竟然没想到==)。。
欸,风萧萧兮易水寒,,,,为何我没有想到,还是自己太蒟蒻了。。。。。。。。
五年之后,纺已经成为海洋学研究科的大学生。 在纺的帮助下,光得知了海面下海流的情况。 纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。 纺帮你绘制了一张海流情况图,长度为 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 需要自己写队列,不然会超时一组。。。。
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 就是爱花的位置。 因为光相信自己一定能找到爱花,所以爱花的位置确定(不会有两个位置满足条件) 。
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 ,b ,c ,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 =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 ; 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; 4000 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" #endif using 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 ; int b ,T,anx,any,tot,num; bool bo ; 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][CSD][表达式的计算]
- [NOIP模拟][数位DP]魔法数字
- Codeforces Round #408 (Div. 2) 思维,模拟,DP, 多点BFS
- [jzoj]3511. 【NOIP2013模拟11.5A组】cza的蛋糕(cake)(DP嵌套dfs【快】或DP【慢】)
- 20160930的考试,noip模拟】SPFA,LIS,状压dp
- 【JZOJ5330】【NOIP提高组模拟】密码(库默尔定理、数位DP)
- [NOIP模拟]BOX(推箱子)-BFS
- 17.7.7 NOIP模拟赛 【模拟/数据结构】【模拟】
- [NOIP 模拟]潜水员 DP
- NOIP模拟dp专题 Question 单调栈
- NOIP模拟试题 软件开发(二分DP)
- JZOJ5379. 【NOIP2017提高A组模拟9.21】Victor爱数字 数位DP
- 递推(DP) noip 模拟 不等数列
- JZOJ5377. 【NOIP2017提高A组模拟9.19】开拓 DP
- 9.27 [NOIP模拟]数据结构 不正常团伙 莫队/主席树
- 9.27 数据结构noip模拟——不正常团伙
- NOIP模拟题 [模拟][DP][线段树]
- 11-1 noip模拟 第二题 SPFA+状压dp
- 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
- 树形dp(人品问题NOIP17提高模拟训练3)