AcWing cup 2022春季

A:水题。

链接:https://www.acwing.com/problem/content/4379/

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 using namespace std;
 6 map<int,int> mp={
 7     {0,1},
 8     {1,0},
 9     {2,0},
10     {3,0},
11     {4,1},
12     {5,0},
13     {6,1},
14     {7,0},
15     {8,2},
16     {9,1},
17     {10,1},
18     {11,2},
19     {12,0},
20     {13,1},
21     {14,0},
22     {15,0}
23 };
24 int main()
25 {
26     int n;
27     cin>>n;
28     if(n==0){
29         cout<<1;
30         return 0;
31     }
32     int res=0;
33     while(n){
34         int t=n%16;
35         res+=mp[t];
36         n/=16;
37     }
38     cout<<res;
39     return 0;
40 }

 

B:数据太小,可直接以数组模拟数轴,暴力求之。

原题链接:https://www.acwing.com/problem/content/4380/

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 210;
 6 int n,k;
 7 int q[N];
 8 bool h[N];
 9 bool check(){
10     for(int i=1;i<=n;i++)
11         if(h[i]==false)
12             return false;
13     return true;
14 }
15 int main()
16 {
17     int T;
18     cin>>T;
19     while(T--){
20         memset(h,0,sizeof h);
21         cin>>n>>k;
22         for(int i=0;i<k;i++){
23             cin>>q[i];
24             h[q[i]]=true;
25         }
26         int cnt=1;
27         while(!check()){
28             cnt++;
29             for(int i=0;i<k;i++){
30                 int t=q[i];
31                 for(int j=max(1,t-cnt+1);j<=min(n,t+cnt-1);j++){
32                     h[j]=true;
33                 }
34             }
35         }
36         cout<<cnt<<endl;
37     }
38     return 0;
39 }

当然,上面说的是暴力,自然就有更快的方法。

枚举两灌溉器之间最后被灌溉到的土地,即可求出灌溉整片农田需要多久。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=210;
 6 int q[N];
 7 int main()
 8 {
 9     int T;
10     cin>>T;
11     while(T--){
12         int n,k;
13         cin>>n>>k;
14         for(int i=1;i<=k;i++) cin>>q[i];
15         int res=max(q[1],n-q[k]+1);
16         for(int i=1;i<k;i++){
17             int t=q[i]+q[i+1]>>1;
18             res=max(res,t-q[i]+1);
19         }
20         cout<<res<<endl;
21     }
22     return 0;
23 }

 

C:dp,是一个较为复杂的dp,特别是状态表示是我没有见过的。

原题链接:https://www.acwing.com/problem/content/4381/

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N=5010;
 7 LL s[N],f[N][N];
 8 int main()
 9 {
10     int n,m,k;
11     cin>>n>>m>>k;
12     for(int i=1;i<=n;i++){
13         int x;
14         cin>>x;
15         s[i]=s[i-1]+x;
16     }
17     memset(f,-0x3f,sizeof f);
18     for(int i=0;i<=n;i++) f[i][0]=0;
19     
20     for(int i=0;i<=n;i++){
21         for(int j=1;j<=k;j++){
22             LL ma=-1;
23             for(int q=(j-1)*m;q<=i-m;q++){
24                 ma=max(ma,f[q][j-1]+s[i]-s[i-m]);
25             }
26             f[i][j]=ma;
27         }
28     }
29     LL res=-1;
30     for(int i=0;i<=n;i++) res=max(res,f[i][k]);
31     cout<<res<<endl;
32     return 0;
33 }

但是此时有三重循环,计算量为5000*5000*5000,若能少一重循环,就能将时间控制在1s以内。

观上述手稿,可以发现最内层循环求得的是f [ (j-1)*m ] [ j-1 ] 到 f [ i-m ] [ j-1 ]的最大值

所以当j固定的时候,左端点便固定了,只有右端点在变化,此时就可用一变量代之。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N=5010;
 7 LL s[N],f[N][N];
 8 int main()
 9 {
10     int n,m,k;
11     cin>>n>>m>>k;
12     for(int i=1;i<=n;i++){
13         int x;
14         cin>>x;
15         s[i]=s[i-1]+x;
16     }
17     memset(f,-0x3f,sizeof f);
18     for(int i=0;i<=n;i++) f[i][0]=0;
19     
20     for(int j=1;j<=k;j++){
21         LL maxf=-1;
22         for(int i=j*m;i<=n;i++){
23             maxf=max(maxf,f[i-m][j-1] + s[i]-s[i-m]);
24             f[i][j]=maxf;
25         }
26     }
27     LL res=-1;
28     for(int i=0;i<=n;i++) res=max(res,f[i][k]);
29     cout<<res<<endl;
30     return 0;
31 }

 

posted on 2022-03-22 20:06  greenofyu  阅读(24)  评论(0编辑  收藏  举报