训练赛后补题 04
2020-06-29 个人训练赛后补题

补题补到心态炸裂……呜呜呜怎么没写的这么多啊
我好菜
好了开始补题:
QAQ完全没发现自己错在哪的第一个提交
WA的代码:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0 }, i; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 } 24 int j, t = 0, ans, flag; 25 ans = 0; 26 for (i = 1; i <= n;) { 27 //cout << i << ":" << a[i] << endl; 28 j = 0; 29 flag = 0; 30 if (a[i]) { 31 i += k; //pass 32 ans++; //help+1 33 } 34 else { 35 flag = 1; 36 t = i; 37 j = i + k - 1; 38 while (j > t) { 39 if (a[j]) { 40 i = j; 41 flag = 0; 42 break; 43 } 44 j--; 45 } 46 } 47 if (flag) { 48 break; 49 } 50 } 51 if (flag || ans == 0)printf("-1\n"); 52 else printf("%d\n", ans); 53 } 54 return 0; 55 }

我太难了55555
////-------------------------------------
去了原题cf看了样例,明白我错在哪了……a[i]=0的时候检索区域大小不应该是k-1,应该是2k-1……
用
6 2
0 1 1 0 0 1
这个数据就不能通过……
可见测试数据范围的重要性
////-------------------------------------
我又又又又叕叒双WA了,WA在了test 5
这次的主函数:
1 int main() { 2 int n, k, a[MAX4] = { 0 }, i; 3 while (scanf("%d %d", &n, &k) != EOF) { 4 for (i = 1; i <= n; ++i) { 5 scanf("%d", &a[i]); 6 } 7 int j, t = 0, ans, flag; 8 ans = 0; 9 for (i = 1; i <= n;) { 10 //cout << i << ":" << a[i] << endl; 11 j = 0; 12 flag = 0; 13 if (a[i]) { 14 i += k; 15 ans++; //help+1 16 } 17 else { 18 flag = 1; 19 if (i > k) 20 t = i - k; 21 else 22 t = i; 23 if (i + k - 2 < n) 24 j = i + k - 1; 25 else j = n; 26 while (j > t) { 27 if (a[j]) { 28 i = j + k; 29 ans++; 30 flag = 0; 31 break; 32 } 33 j--; 34 } 35 } 36 if (flag) { 37 break; 38 } 39 } 40 if (flag || ans == 0)printf("-1\n"); 41 else printf("%d\n", ans); 42 } 43 return 0; 44 }
这次的失败样例是:
【太长了网站没给全】
1000 100 0 1……正答6,输出8
emmmm我瞅瞅咋多了
emmm这份代码逻辑有个隐患,就是:代码本身是每次往后检索最远的接应点,但是对于样例,可能部分挨着的接应点能满足更少的数量……总之就是极端样例不通过。
so我去看了题解……我真的真的恨不熟练贪心。
还能怎么办呢,学呗。
////------------------坚定自己代码逻辑有实现可能的我贼心不死,又去修改原先的代码了
这次能通过了,但是超时了【泣不成声】
以下是在样例10超时的代码:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0 }, i, flag = 0; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 } 24 int rf, lf = 0, ans, flag = 0; 25 ans = 0; 26 for (i = 1; i <= n;) { //从前方洞穴往后检测 27 //失误点:第一个风洞非必要选择 28 //cout << i << ":" << a[i] << endl; 29 rf = 0; 30 flag = 1; //假设前后风洞都不能使当前洞可走 31 if (i > k) //前方最远风洞距离限制 32 lf = i - k; 33 else 34 lf = 1; 35 if (i + k - 2 < n) //后方最远风洞距离限制 36 rf = i + k - 1; 37 else 38 rf = n; 39 while (rf >= lf) { //从后方往前检测 40 if (a[rf]) { //检测到风洞 41 i = rf + k; //下一监测点为风洞影响范围外邻点 42 ans++; //所用风洞数+1 43 flag = 0; //这一段路可走了 44 break; //暂停检测,进入下一监测点 45 } 46 rf--; 47 } 48 //cout << "check finished" << endl;//test 49 if (flag) { //出现没有前后风洞能接力的洞,退出检测 50 break; 51 } 52 } 53 if (flag || ans == 0)printf("-1\n"); 54 else printf("%d\n", ans); 55 } 56 return 0; 57 }
emmmm接下来按照这个逻辑优化试试
总结一下逻辑规律:每次找出范围内的最后一个风洞,不过是从前往后
卧槽,这……这本质上就是贪心啊【惊】
////----------------7.04更新!我终于AC辣!!!
尤其是,我发现我离AC只有一步之遥——没错把其中一个顺序调换一下,就不需要多余的检测了!
下面是AC代码,我太难了55555
不过AC了真高兴
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0 }, s[MAX4] = { 0 }, i, flag = 0; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 s[i] = s[i - 1] + a[i]; //前几个洞中有多少风洞 24 } 25 int rf, lf = 0, ans, flag = 0; 26 ans = 0; 27 for (i = 1; i <= n;) { //从前方洞穴往后检测 28 //失误点:第一个风洞非必要选择 29 //cout << i << ":" << a[i] << endl; 30 rf = 0; 31 flag = 1; //假设前后风洞都不能使当前洞可走 32 if (i > k - 1) //前方最远风洞距离限制 33 lf = i - k + 1; 34 else 35 lf = 1; 36 if (i + k - 2 < n) //后方最远风洞距离限制 37 rf = i + k - 1; 38 else 39 rf = n; 40 if (s[rf] - s[lf - 1] == 0) //距离限制范围内无风洞,退出检测 41 break; 42 else 43 while (rf >= lf) { //从后方往前检测 44 if (a[rf]) { //检测到风洞 45 i = rf + k; //下一监测点为风洞影响范围外邻点 46 ans++; //所用风洞数+1 47 flag = 0; //这一段路可走了 48 break; //暂停检测,进入下一监测点 49 } 50 rf--; 51 } 52 //cout << "check finished" << endl;//test 53 } 54 if (flag || ans == 0)printf("-1\n"); 55 else printf("%d\n", ans); 56 } 57 return 0; 58 }
////------------------7.06更新……队里大佬说自己打出题要比照着题解打好很多,嘿嘿嘿我也这么觉得。
我这次认真查了一下贪心
强烈安利一个大佬哦,博客写得超级好理解
网址:https://blog.csdn.net/jxhaha/article/details/78762412
另外我还做了些笔记:
活动选择:对于互斥不可重复活动,始终选取结束时间最早的活动作为解集合成员,每次抽取结束时间最早的活动。
0 - 1背包:F[i,j] = max(F[i-1,j],F[i-1,j-Wi]+Vi) 适用:每个物体只抽一次取最大重量方案
完全背包:F[i,j]=max(f[i-1,j], f[i,j-Wi]+Vi) 适用:能多次选择同一物体取最大重量
多重背包:F[i,j] = max(F[i-1,j],F[i, j-Wi*k]+Vi*k 适用:规定次数内可选同一物品时取最大重量
膜拜大佬!

浙公网安备 33010602011771号