5.20考试整理
水灾(sliker.cpp/c/pas)
1000MS 64MB
大雨应经下了几天雨,却还是没有停的样子。土豪CCY刚从外地赚完1e元回来,知道不久除了自己别墅,其他的地方都将会被洪水淹没。
CCY所在的城市可以用一个N*M(N,M<=50)的地图表示,地图上有五种符号:“. * X D S”。其中“X”表示石头,水和人都不能从上面经过。“.”表示平原,CCY和洪水都可以经过。“*”表示洪水开始地方(可能有多个地方开始发生洪水)。“D”表示CCY的别墅。“S”表示CCY现在的位置。
CCY每分钟可以向相邻位置移动,而洪水将会在CCY移动之后把相邻的没有的土地淹没(从已淹没的土地)。
求CCY回到别墅的最少时间。如果聪哥回不了家,就很可能会被淹死,那么他就要膜拜黄金大神涨RP来呼叫直升飞机,所以输出“ORZ hzwer!!!”。
输入文件 sliker.in
输出文件 sliker.out
#1
Input
3 3
D.*
…
.S.
Output
3
#2
Input
3 3
D.*
…
..S
Output
ORZ hzwer!!!
#3
Input
3 6
D…*.
.X.X..
….S.
Output
6
谈心:
这道题就是一道广搜的题,但是我不会写..因为我觉得有好多个洪水一起开始发洪水没法写,但是是这样是错的,其实是能够写的,用队列啊!
在最后快要交卷的时候我想到了,但是因为没时间写了.所以没有写完.
而且我的数组开炸了...知道消息后我的内心是崩溃的!
明明在变量的后面敲上了注释范围,可是开数组的时候用M开的.qwq
思路:
首先bfs出每个点被淹没需要的时间,然后再bfs洪水:如果是洪水就让他入队,然后扩展状态,如果扩展到的状态"淹没了"这个人(不知道他是谁),就输出"ORZ hzwer!!!"
代码酱=u=
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <queue> #include <cmath> #define INF 0x7fffffff using namespace std; const int M = 55; const int N = 1e4 + 5; int n,m,cnt;//<=50 int dx[5] = {0,0, 0,1,-1}, dy[5] = {0,1,-1,0, 0};//right left down up int jz[M][M]; bool v[M][M]; char cc[M]; int sx,sy,ex,ey; struct AA{ int x,y,step,f; }zz[N],cv; queue<AA>QwQ; inline int read() { int x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } void bfs1() { int xx,yy; while(!QwQ.empty()) { cv=QwQ.front(); int x=cv.x,y=cv.y; QwQ.pop(); for(int i=1;i<=4;i++) { xx=x+dx[i]; yy=y+dy[i]; if(xx>n || xx<1 || yy>m || yy<1 || v[xx][yy]) continue; if((xx==ex && yy==ey) || jz[xx][yy]!=INF) continue; jz[xx][yy]=jz[x][y]+1; cv.x=xx,cv.y=yy; QwQ.push(cv); } } } void bfs2() { while(!QwQ.empty()) QwQ.pop();//qing kong // for(int i=1;i<=cnt;i++) // QwQ.push(zz[i]); zz[0].x=sx,zz[0].y=sy; QwQ.push(zz[0]); int xx,yy; while(!QwQ.empty()) { cv=QwQ.front(); int x=cv.x,y=cv.y,step=cv.step; QwQ.pop(); for(int i=1;i<=4;i++) { xx=x+dx[i]; yy=y+dy[i]; if(xx>n || xx<1 || yy>m || yy<1 || v[xx][yy] || step+1>=jz[xx][yy]) continue; v[xx][yy]=true; if(xx==ex && yy==ey) { printf("%d",step+1); return; } cv.x=xx,cv.y=yy,cv.step=step+1; QwQ.push(cv); } } printf("ORZ hzwer!!!"); } int main() { // freopen("sliker.in","r",stdin); // freopen("sliker.out","w",stdout); n=read(),m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) jz[i][j]=INF;//chu shi hua for(int i=1;i<=n;i++) { scanf("%s",cc); for(int j=1;j<=m;j++) { if(cc[j-1] == 'D') {ex=i;ey=j;} if(cc[j-1] == 'S') {sx=i;sy=j;} if(cc[j-1] == 'X') v[i][j]=1; if(cc[j-1] == '*') { zz[++cnt].x=i; zz[cnt].y=j; QwQ.push(zz[cnt]); jz[i][j]=0; } } } bfs1(); bfs2(); return 0; } /* 3 6 D...*. .X.X.. ....S. 6 3 3 D.* ... .S. 3 3 3 D.* ... ..S ORZ hzwer!!! */
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #define inf 0x7fffffff using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x*=10;x+=ch-'0';ch=getchar();} return x*f; } int n,m,bx,by,ex,ey; int t,w; int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1}; char ch[55]; bool mp[55][55]; int tim[55][55]; struct data{int x,y,step,f;}q[10005]; void bfs1() { while(t!=w) { int x=q[t].x,y=q[t].y;t++; for(int i=0;i<4;i++) { int nowx=x+xx[i],nowy=y+yy[i]; if(nowx>n||nowy>m||nowx<1||nowy<1||mp[nowx][nowy])continue; if((nowx==ex&&nowy==ey)||tim[nowx][nowy]!=inf)continue; tim[nowx][nowy]=tim[x][y]+1; q[w].x=nowx;q[w].y=nowy;w++; } } } void bfs2() { t=0,w=1;q[0].x=bx;q[0].y=by; while(t!=w) { int x=q[t].x,y=q[t].y,step=q[t].step;t++; for(int i=0;i<4;i++) { int nowx=x+xx[i],nowy=y+yy[i]; if(nowx>n||nowy>m||nowx<1||nowy<1||mp[nowx][nowy]||step+1>=tim[nowx][nowy]) continue; mp[nowx][nowy]=1; if(nowx==ex&&nowy==ey){printf("%d",step+1);return;} q[w].x=nowx;q[w].y=nowy;q[w].step=step+1;w++; } } printf("ORZ hzwer!!!"); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) tim[i][j]=inf; for(int i=1;i<=n;i++) { scanf("%s",ch); for(int j=1;j<=m;j++) { if(ch[j-1]=='D'){ex=i;ey=j;} if(ch[j-1]=='S'){bx=i;by=j;} if(ch[j-1]=='X')mp[i][j]=1; if(ch[j-1]=='*'){q[w].x=i;q[w].y=j;tim[i][j]=0;w++;} } } bfs1(); bfs2(); return 0; }
某种数列问题 (jx.cpp/c/pas)
1000MS 256MB
众所周知,chenzeyu97有无数的妹子(阿掉!>_<),而且他还有很多恶趣味的问题,继上次纠结于一排妹子的排法以后,今天他有非(chi)常(bao)认(cheng)真(zhe)去研究一个奇怪的问题。有一堆他的妹子站成一排,然后对于每个妹子有一个美丽度,当然美丽度越大越好,chenzeyu97妹子很多,但是质量上不容乐观,经常出现很多美丽度为负数的妹子(喜闻乐见),chenzeyu97希望从一排妹子里找出3队连续的妹子,使她们的美丽度和最大。注意,一个妹子不能被编入多个队伍而且一定要拿出三队,不然czy会闲着没事做~。
简单滴说就是:
给定一个数列,从中找到3个无交集的连续子数列使其和最大。
【输入文件】
第一行一个数n,表示数列长度。
接下来有n行,每行一个数,第i行为第i个数。
【输出文件】
仅有一个数,表示最大和。
【样例输入】 jx.in
10
-1
2
3
-4
0
1
-6
-1
1
-2
【样例输出】 jx.out
7
【样例说明】
第一队妹子取2,3。
第二队妹子取0,1。
第三队妹子取1。
【数据范围】
请大家放心,虽然chenzeyu97妹子无数,但是这次他叫来的个数n是有限的。=v=
对于30%的数据,妹子数不大于200。
对于60%的数据,妹子数不大于2000。
对于100%的数据,妹子数1000000。
而且,由于chenzeyu97没有CCR那样的影响力,所以他的妹子选完的最大美丽度和不超过maxlongint。(注:CCR随便选就爆long long,因为他是把妹狂魔=V=)。
思路:
恶心的DP
代码酱=u=
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <cmath> using namespace std; typedef long long LL; const int M = 1e6 + 1; LL n; LL ans; LL QwQ; LL f[M][4][2]; //第几元素,第几队,该元素是否被选择 //f里面存的是到当前元素的最大解 inline LL read()//读入优化 { LL x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } int main() { n=read(); //初始化f数组,因为要取最'大'值 memset(f,-127,sizeof(f)); for(LL i=1;i<=n;i++) { //读入下一个元素 QwQ=read(); /* 如果当前元素在第一队 ①选上当前元素,所以需要判断一下前面的选不选 如果他是当前队的第一个元素,直接更新为本身的值就好啦 如果不是第一个元素,就用选上上一个元素的f值更新 在这两种情况中取出一个最大值更新 ②不选当前元素, 所以当前的最大值就是用上一个状态来更新的 */ f[i][0][1]=max(QwQ,f[i-1][0][1]+QwQ); f[i][0][0]=max(f[i-1][0][0],f[i-1][0][1]); /* 如果当前元素在第二队 ①选上当前元素,所以需要判断一下前面的选不选 如果他是当前队的第一个元素,直接更新为本身的值加上上一队的最大值 如果不是第一个元素,就用选上上一个元素的f值加上当前元素的值更新 因为这是第二队!!! 然后在这两种情况中取出一个最大值更新 ②不选当前元素, 所以当前的最大值就是用上一个状态来更新的 */ f[i][1][1]=max(QwQ+f[i-1][0][0],QwQ+f[i-1][1][1]); f[i][1][0]=max(f[i-1][1][0],f[i-1][1][1]); //如果当前元素在第三队 //同 f[i][2][1]=max(QwQ+f[i-1][1][0],QwQ+f[i-1][2][1]); f[i][2][0]=max(f[i-1][2][1],f[i-1][2][0]); } ans=max(f[n][2][0],f[n][2][1]); cout<<ans; /* if(cnt<=2 || (mz[1]<0 && cnt==3) || (mz[n]<0 && cnt==3) || (mz[1]<0 && mz[i-1]<0 && cnt==4)) { printf("%d",ans); return 0; } */ return 0; }
密码锁
1000MS 512MB
Input: password.in
Output: password.out
【题目描述】
hzwer有一把密码锁,由N个开关组成。一开始的时候,所有开关都是关上的。当且仅当开关x1,x2,x3,...xk为开,其他开关为关时,密码锁才会打开。
他可以进行M种的操作,每种操作有一个size[i],表示,假如他选择了第i种的操作的话,他可以任意选择连续的size[i]个格子,把它们全部取反。(注意,由于黄金大神非常的神,所以操作次数可以无限>_<)
本来这是一个无关紧要的问题,但是,黄金大神不小心他的钱丢进去了,没有的钱他哪里能逃过被chenzeyu97 NTR的命运?>_< 于是,他为了虐爆czy,也为了去泡更多的妹子,决定打开这把锁。但是他那么神的人根本不屑这种”水题”。于是,他找到了你。
你的任务很简单,求出最少需要多少步才能打开密码锁,或者如果无解的话,请输出-1。
【输入格式】
第1行,三个正整数N,K,M,如题目所述。
第2行,K个正整数,表示开关x1,x2,x3..xk必须为开,保证x两两不同。
第三行,M个正整数,表示size[i],size[]可能有重复元素。
【输出格式】
输出答案,无解输出-1。
【样例输入1】
10 8 2
1 2 3 5 6 7 8 9
3 5
【样例输出1】
2
【样例输入2】
3 2 1
1 2
3
【样例输出2】
-1
【数据规模】
对于50%的数据,1≤N≤20,1≤k≤5,1≤m≤3;
对于另外20%的数据,1≤N≤10000,1≤k≤5,1≤m≤30;
对于100%的数据,1≤N≤10000,1≤k≤10,1≤m≤100。
思路+代码: