5.20考试整理
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 <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 [2][0],f [2][1]); cout<<ans; /* if(cnt<=2 || (mz[1]<0 && cnt==3) || (mz <0 && cnt==3) || (mz[1]<0 && mz[i-1]<0 && cnt==4)) { printf("%d",ans); return 0; } */ return 0; }DP
密码锁
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。
思路+代码: