11月月赛
A-HDU1087 http://acm.hdu.edu.cn/showproblem.php?pid=1087
相当于从数组a中找一个最优序列,我们设要找的序列为A,序列A满足两个条件,一是A中的元素大小满足单调递增,二是A中所有元素的和最大,输出这个最大值。
令f[i]表示以第i个元素结尾的A序列的最大值,则有f[i]=MAX{ f[j]+a[i] | j<i } ans=MAX{f[i]};
#include<bits/stdc++.h> using namespace std; int main() { int N,i,j,k,ans; int f[1005],a[1005]; while(cin>>N&&N){ memset(f,0,sizeof(f)); ans=0; for(i=1;i<=N;++i) cin>>a[i]; for(i=1;i<=N;++i){ int maxn=0; for(j=1;j<i;++j){ if(a[j]<a[i]&&f[j]>maxn) maxn=f[j]; } f[i]=maxn+a[i]; ans=max(ans,f[i]); } cout<<ans<<endl; } return 0; }
B-HDU5586 http://acm.hdu.edu.cn/showproblem.php?pid=5586
对于数组A可以选定任意一段连续的区间[l,r]将这段区间的值改变为: A[i]=(1890*A[i]+143)%10007; 求更改之后A数组的总和的最大值。
不妨这么想,这个最大值就是未改变之前的A数组的总和加上改变的那段区间改变以后增加的值X,问题就转化为求最大的X,
设B[i]=(1890*A[i]+143)%10007,C[i]=B[i]-A[i]; 显然X就是C数组的一个最大子段和,找到之后输出SUM{A[i]}+X即可。
#include<bits/stdc++.h> using namespace std; int main() { int N,M,i,j,k,t,a,b; while(scanf("%d",&N)==1){ int s=0,maxn=0,sumn=0; for(i=1;i<=N;++i){ scanf("%d",&a); s+=a; b=1890*a+143; if(b>10006) b=b%10007-a; else b-=a; sumn+=b; if(sumn>maxn) maxn=sumn; if(sumn<0) sumn=0; } printf("%d\n",s+maxn); } return 0; }
C-uva10910 https://vjudge.net/problem/UVA-10910
F(N,T,P)表示N门不同的课程,总共得分T分,没门至少得分P分,求不同的得分方案总数。
1是dp,令f(i,j)表示前i门课程得了j分的方案个数,枚举最后一门课程得分k,有f[i][j]=SUM{f[i-1][j-k] | P<=k<=T&&0<=j-k<=T}
#include<bits/stdc++.h> using namespace std; #define LL long long int f[105][105]; int main() { int T,N,P,cas,i,j,k; cin>>cas; while(cas--){ cin>>N>>T>>P; memset(f,0,sizeof(f)); f[0][0]=1; for(i=1;i<=N;++i) { for(j=P*i;j<=T;j++) { for(k=P;k<=T;++k) { if(j-k<=T&&j-k>=0) f[i][j]+=f[i-1][j-k]; } } } cout<<f [T]<<endl; } return 0; }
2-组合数学
利用组合数学,题目转换为将T-N*P个小球(相同)放入N个盒子(不同)的方案个数,显然是C(T-N*P+N-1,T-N*P)-------->数学公式我只会背不会推导
#include<bits/stdc++.h> using namespace std; #define LL long long LL C(LL N,LL M) { LL ans=1; for(LL i=1;i<=M;++i) { ans=ans*(N-i+1)/i; } return ans; } int main() { LL N,T,P; int k; cin>>k; while(k--){ cin>>N>>T>>P; cout<<C(T-N*P+N-1,T-N*P)<<endl; } return 0; }
D-HDU1243 http://acm.hdu.edu.cn/showproblem.php?pid=1243
一个标准的LCS模型,只不过多了权值,稍微改下转移方程就好了,令kill(i)表示杀死第i个人的得分
f[i][j]=MAX{f[i-1][j-1]+kill(i) | if(s1[i]==s2[j]) , f[i-1][j] , f[i][j-1] }
#include<bits/stdc++.h> using namespace std; int f[2105][2105]; int value[30]; char s1[2105],s2[2105],s[2105]; int main() { int N; int i,j,k,n,m; while(cin>>N){ cin>>s+1; for(i=1;i<=N;++i) cin>>value[s[i]-'a']; cin>>s1+1>>s2+1; int len1=strlen(s1+1); int len2=strlen(s2+1); memset(f,0,sizeof(f)); for(i=1;i<=len1;++i){ for(j=1;j<=len2;++j){ if(s1[i]==s2[j]){ f[i][j]=max(f[i][j],f[i-1][j-1]+value[s1[i]-'a']); } f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1])); } } cout<<f[len1][len2]<<endl; } return 0; }
E-HDU2845 http://acm.hdu.edu.cn/showproblem.php?pid=2845
其实就是求最大不连续子段和,先求出每一行的最大不连续子段和,再把每一行求出的值看作一个序列再求一次最大不连续子段和就是答案。
令f[i]表示前i个元素中的最大不连续子段和,有f[i]=max(f[i-1],a[i]+f[i-2]);
#include<bits/stdc++.h> using namespace std; int dp[200005]; int h[200005]; int book[200005]; int n,m; int init(int a[],int len) { dp[0]=0; dp[1]=a[1]; for(int i=2;i<=len;++i) dp[i]=max(a[i]+dp[i-2],dp[i-1]); return dp[len]; } int main() { int i,j,k; while(cin>>n>>m){int s1=0,s2=0; for(i=1;i<=n;++i){ for(j=1;j<=m;++j) scanf("%d",&h[j]); book[i]=init(h,m); } printf("%d\n",init(book,n)); } return 0; }
- 【洛谷月赛】洛谷11月月赛·Day1
- 【FOJ2205 11月月赛A】【二分图结论题】据说题目很水 n个点上不形成三元环的最大边数
- 【FOJ2206 11月月赛B】【观察找规律】函数求解 分析函数求值
- 【FOJ2210 11月月赛F】【DFS or 拓扑排序】攻占计划 n个点m条边DAG破坏一个点使得不可达点数尽可能多
- 【FOJ2207 11月月赛C】【DFS栈性质应用 离线处理】以撒的结合 从x到y路径上的第k个点 询问众多
- 洛谷11月月赛round.2
- 武汉科技大学计算机学院11月月赛:母牛的故事
- 武汉科技大学计算机学院11月月赛:Draw Something
- 武汉科技大学计算机学院11月月赛:Hunters
- 武汉科技大学计算机学院11月月赛:The Little Girl who Picks Mushrooms
- [codeplus 11月月赛]T1 jogging
- 武汉科技大学计算机学院11月月赛:WHUgirls
- FOJ 11月月赛题解
- [codeplus 11月月赛]T2 timber
- 武汉科技大学计算机学院11月月赛:A+B
- 洛谷11月月赛 T1 高兴的津津
- 洛谷11月月赛 T2 不开心的金明
- FZU 11月月赛D题:双向搜索+二分
- fzoj11月有奖月赛ytaaa
- 洛谷11月月赛 T3 斐波那契数列