A
最长上升子序列
基础dp 状态转移方程 dp[i]=max(dp[i],dp[j]+1),j<i&&A[j]<A[i]
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int A[1007]; 5 int dp[1007]={0}; 6 int main() 7 { 8 int n,i,j,k; 9 cin>>n; 10 for(i=1;i<=n;++i) cin>>A[i]; 11 for(i=1;i<=n;++i) 12 { 13 for(j=1;j<i;++j) 14 { 15 if(A[j]<A[i]) dp[i]=max(dp[i],dp[j]+1); 16 } 17 } 18 int ans=-1; 19 for(i=1;i<=n;++i) ans=max(ans,dp[i]); 20 cout<<ans+1<<endl; 21 return 0; 22 }
B
一维线性dp
思路:兔子所用时间 T=L/VR. 对于乌龟,可以把每个充电桩近似看成终点,计算乌龟到每个充电桩的最短时间,可以推出到终点的最短时间。 设 j<i 且 j到i的最短时间为time,lx 为j到i的距离 则 lx<=C:time=lx/VT1; lx>C:time=C/VT1+(lx-C)/VT2;
状态转移方程 dp[i]=min(dp[i],dp[j]+time)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int inf=0x3f3f3f3f; 5 double A[1007]; 6 double dp[1007]={0}; 7 int main() 8 { 9 int n,i,j,k; 10 double L,N,C,VR,VT1,VT2,T; 11 while(cin>>L) 12 { 13 cin>>n>>C>>T; 14 cin>>VR>>VT1>>VT2; 15 for(i=1;i<=n;++i) cin>>A[i]; 16 double fx=L/VR; 17 A[n+1]=L; A[0]=0; 18 for(i=1;i<=n+1;++i) 19 { 20 dp[i]=inf; dp[0]=0; 21 for(j=0;j<i;++j) 22 { 23 double time=0; 24 double l=A[i]-A[j]; 25 if(l<=C) 26 { 27 time=time+l/VT1; 28 } 29 else { 30 time=time+C/VT1+(l-C)/VT2; 31 } 32 if(j) time+=T; 33 dp[i]=min(dp[i],dp[j]+time); 34 } 35 } 36 // printf("%.2f %.2f ",fx,dp[n+1]); 37 if(dp[n+1]<fx) printf("What a pity rabbit! "); 38 else printf("Good job,rabbit! "); 39 } 40 41 return 0; 42 }
C
签到题
0-向左跳的距离+向右跳的距离
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int A[1007]; 5 int main() 6 { 7 ll x,y,z,t; 8 cin>>t; 9 while(t--) 10 { 11 ll ans=0; 12 cin>>x>>y>>z; 13 ans=ans-y*(z/2)+x*(z-z/2); 14 cout<<ans<<endl; 15 } 16 return 0; 17 }
D
贪心
每次遇到 1 0 1 这种情况变为 1 0 0 即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int A[1007]; 5 int main() 6 { 7 ll n,i,j,k,t; 8 ll x,y,z; 9 cin>>n; 10 for(i=1;i<=n;++i) 11 { 12 cin>>A[i]; 13 } 14 int ans=0; 15 for(i=2;i<n;++i) 16 { 17 if(A[i]==0&&A[i-1]==1&&A[i+1]==1) 18 { 19 ans++;A[i+1]=0; 20 //cout<<i<<endl; 21 } 22 } 23 cout<<ans<<endl; 24 return 0; 25 }
E
思维 枚举
先求出数组总和值sum,枚举数组中每一个数x,将其减去 sum-=x; 判断一下sum/2 数组中剩下的数中是否存在,若存在,将数x存到另一个数组里。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int qs=2e5+7; 5 int A[qs]; 6 int B[qs]; 7 map<int,int> mp; 8 int main() 9 { 10 ll n,i,j,k,t,x; 11 cin>>n; 12 ll sum=0; 13 for(i=1;i<=n;++i) 14 { 15 cin>>A[i]; sum+=A[i]; mp[A[i]]++; 16 } 17 int ans=0; 18 for(i=1;i<=n;++i) 19 { 20 mp[A[i]]--; 21 double x=(double)(sum-A[i])/2; 22 if(x==(int)x&&mp[(int)x]>0) { 23 B[ans]=i;ans++; 24 } 25 mp[A[i]]++; 26 } 27 cout<<ans<<endl; 28 for(i=0;i<ans;++i) 29 { 30 if(i==ans-1) printf("%d ",B[i]); 31 else printf("%d ",B[i]); 32 } 33 return 0; 34 }
F
二分
思路:通过求重复次数x,在重复x中找到一个序列 L,若L的长度大于等于k,即满足要求。则二分求解重复次数x即可。
// 自己做的时候没想到二分emmm....
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int qs=2e5+7; 5 map<int,int> mp; 6 vector<int> v,c; 7 int ck(int mid) 8 { 9 c.clear(); 10 for(int i=0;i<v.size();++i) 11 { 12 int num=mp[v[i]]/mid; 13 for(int j=0;j<num;++j) c.push_back(v[i]); 14 } 15 return c.size(); 16 } 17 int n,m; 18 int main() 19 { 20 int i,j,k,x,y; 21 cin>>n>>m; 22 int l,r; 23 y=-1; 24 for(i=1;i<=n;++i) 25 { 26 cin>>x; 27 if(!mp[x]) { mp[x]=0; 28 v.push_back(x); 29 } 30 mp[x]++; y=max(mp[x],y); 31 } 32 l=1;r=y; 33 int ans=0; 34 while(l<=r) 35 { 36 int mid=(l+r)/2; 37 if(ck(mid)>=m) 38 { 39 l=mid+1; ans=mid; 40 } 41 else r=mid-1; 42 } 43 int xx=ck(ans); 44 for(i=0;i<m;++i) 45 { 46 if(i==m-1) printf("%d ",c[i]); 47 else printf("%d ",c[i]); 48 } 49 return 0; 50 }