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 }