• 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]};

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5     int N,i,j,k,ans;
     6     int f[1005],a[1005];
     7     while(cin>>N&&N){
     8         memset(f,0,sizeof(f));
     9         ans=0;
    10         for(i=1;i<=N;++i) cin>>a[i];
    11         for(i=1;i<=N;++i){
    12             int maxn=0;
    13             for(j=1;j<i;++j){
    14                 if(a[j]<a[i]&&f[j]>maxn) maxn=f[j];
    15             }
    16             f[i]=maxn+a[i];
    17             ans=max(ans,f[i]);
    18         }
    19         cout<<ans<<endl;
    20     }
    21     return 0;
    22 }

    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即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5     int N,M,i,j,k,t,a,b;
     6     while(scanf("%d",&N)==1){
     7         int s=0,maxn=0,sumn=0;
     8         for(i=1;i<=N;++i){
     9             scanf("%d",&a);
    10             s+=a;
    11             b=1890*a+143;
    12             if(b>10006) b=b%10007-a;
    13             else  b-=a;
    14             sumn+=b;
    15             if(sumn>maxn) maxn=sumn;
    16             if(sumn<0) sumn=0;
    17         }
    18        printf("%d
    ",s+maxn);
    19     }
    20     return 0;
    21 }

    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}

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 int f[105][105];
     5 int main()
     6 {
     7     int T,N,P,cas,i,j,k;
     8     cin>>cas;
     9     while(cas--){
    10         cin>>N>>T>>P;
    11         memset(f,0,sizeof(f));
    12         f[0][0]=1;
    13         for(i=1;i<=N;++i)
    14         {
    15             for(j=P*i;j<=T;j++)
    16             {
    17                 for(k=P;k<=T;++k)
    18                 {
    19                     if(j-k<=T&&j-k>=0)
    20                     f[i][j]+=f[i-1][j-k];
    21                 }
    22             }
    23         }
    24         cout<<f[N][T]<<endl;
    25     }
    26     return 0;
    27 }

     2-组合数学

      利用组合数学,题目转换为将T-N*P个小球(相同)放入N个盒子(不同)的方案个数,显然是C(T-N*P+N-1,T-N*P)-------->数学公式我只会背不会推导

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 LL C(LL N,LL M)
     5 {
     6     LL ans=1;
     7     for(LL i=1;i<=M;++i)
     8     {
     9         ans=ans*(N-i+1)/i;
    10     }
    11     return ans;
    12 }
    13 int main()
    14 {
    15     LL N,T,P;
    16     int k;
    17     cin>>k;
    18     while(k--){
    19         cin>>N>>T>>P;
    20         cout<<C(T-N*P+N-1,T-N*P)<<endl;
    21     }
    22     return 0;
    23 }

    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] }

      

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int f[2105][2105];
     4 int value[30];
     5 char s1[2105],s2[2105],s[2105];
     6 int main()
     7 {
     8     int N;
     9     int i,j,k,n,m;
    10     while(cin>>N){
    11         cin>>s+1;
    12         for(i=1;i<=N;++i) cin>>value[s[i]-'a'];
    13         cin>>s1+1>>s2+1;
    14         int len1=strlen(s1+1);
    15         int len2=strlen(s2+1);
    16         memset(f,0,sizeof(f));
    17         for(i=1;i<=len1;++i){
    18             for(j=1;j<=len2;++j){
    19                 if(s1[i]==s2[j]){
    20                     f[i][j]=max(f[i][j],f[i-1][j-1]+value[s1[i]-'a']);
    21                 }
    22                 f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1]));
    23             }
    24         }
    25         cout<<f[len1][len2]<<endl;
    26     }
    27     return 0;
    28 }

    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]);

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int dp[200005];
     4 int h[200005];
     5 int book[200005];
     6 int n,m;
     7 int init(int a[],int len)
     8 {
     9     dp[0]=0;
    10     dp[1]=a[1];
    11     for(int i=2;i<=len;++i)
    12         dp[i]=max(a[i]+dp[i-2],dp[i-1]);
    13 return dp[len];
    14 }
    15 int main()
    16 {
    17     int i,j,k;
    18     while(cin>>n>>m){int s1=0,s2=0;
    19         for(i=1;i<=n;++i){
    20           for(j=1;j<=m;++j)
    21      scanf("%d",&h[j]);
    22      book[i]=init(h,m);
    23           }
    24     printf("%d
    ",init(book,n));
    25     }
    26     return 0;
    27 }
  • 相关阅读:
    三级菜单python写法(递归写法)
    webstorm2018.1.6版本安装+破解+汉化
    sourceTree 的使用教程
    nodeppt的使用教程
    堆和栈的区别(转过无数次的文章)
    黎曼滤波在神经计算方面的应用
    深度学习笔记——PCA原理与数学推倒详解
    TCP/IP模型详解
    OSI7层模型详解
    CNN车型分类总结
  • 原文地址:https://www.cnblogs.com/zzqc/p/7787170.html
Copyright © 2020-2023  润新知