训练赛后补题 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    适用:规定次数内可选同一物品时取最大重量

膜拜大佬!

posted @ 2020-07-08 22:35  听说福建人很好吃  阅读(148)  评论(0)    收藏  举报