• hdu 5693 && LightOj 1422 区间DP


    hdu 5693

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5693

    等差数列当划分细了后只用比较2个或者3个数就可以了,因为大于3的数都可以由2和3组合成。

    区间DP,用dp[i][j]表示在i到j之间可以删除的最大数,枚举区间长度,再考虑区间两端是否满足等差数列(这是考虑两个数的),再i到j之间枚举k,分别判断左端点右端点和k是否构成等差数列(还是考虑两个数的),判断左端点,k,右端点是否构成等差数列(这是考虑三个数的)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int M = 300 + 10;
     8 
     9 bool vis[M][M];
    10 int dp[M][M],n,m,a[M];
    11 int max(int x,int y){return x>y?x:y;}
    12 
    13 void solvedp()
    14 {
    15     for (int len=1 ; len<=n ; len++){
    16         for (int l=1 ; l<=n ; l++){
    17             int r=l+len;
    18             if (r>n) break;
    19             if (vis[l][r]&&dp[l+1][r-1]==r-l-1)
    20                 dp[l][r]=max(dp[l][r],dp[l+1][r-1]+2);
    21             for (int i=l ; i<=r ; i++)
    22                 dp[l][r]=max(dp[l][r],dp[l][i]+dp[i+1][r]);
    23             for (int i=l+1 ; i<r ; i++){
    24                 if (vis[l][i]&&dp[l+1][i-1]==i-l+1)
    25                     dp[l][r]=max(dp[l][r],dp[l+1][i-1]+dp[i+1][r]+2);
    26                 if (vis[i][r]&&dp[i+1][r-1]==r-i-1)
    27                     dp[l][r]=max(dp[l][r],dp[l][i-1]+dp[i+1][r-1]+2);
    28                 if (vis[l][i]&&vis[i][r]&&dp[l+1][i-1]==i-l-1&&dp[i+1][r-1]==r-i-1
    29                     &&a[r]-a[i]==a[i]-a[l])
    30                     dp[l][r]=max(dp[l][r],r-l+1);
    31             }
    32         }
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     int t;
    39     scanf("%d",&t);
    40     while (t--){
    41         memset(vis,false,sizeof(vis));
    42         memset(dp,0,sizeof(dp));
    43         scanf("%d%d",&n,&m);
    44         for (int i=1 ; i<=n ; i++) scanf("%d",&a[i]);
    45         for (int i=1 ; i<=m ; i++) {
    46             int x;
    47             scanf("%d",&x);
    48             for (int i=1 ; i<=n ; i++)
    49                for (int j=i+1 ; j<=n ; j++)
    50                   if (a[j]-a[i]==x)
    51                       vis[i][j]=true;
    52         }
    53         solvedp();
    54         printf("%d
    ",dp[1][n]);
    55     }
    56 
    57     return 0;
    58 }
    View Code


    lightoj 1422

    有n个party,姑娘参加每个party都必须穿规定好的种类的衣服,可以将多件不同种类的衣服都套在身上,只要最外面的一层衣服满足party的规定就行了,但是一旦脱下的衣服就不能再次穿上,问最少需要多少件衣服。

    比如第二组样例 1 2 1 1 3 2 1   先穿上种类1的衣服参加晚会1 ,不脱然后继续穿上种类2的衣服参加晚会2,再脱下种类2衣服参加晚会3,4,然后再穿上种类3衣服参加晚会5,再脱下它穿上种类2衣服参加晚会6,在脱下它,此时身上只剩种类1衣服,刚好参加最后一个晚会,所以需要种类1 2 3 2 四件衣服。 

    乍一看就是当遇见之前没有遇见过的种类的衣服的时候,答案肯定要加一,当遇到了之前见过的种类的衣服,此时就要考虑是否穿上这件衣服也就是答案是否要加一,此时就一个用到二维区间dp,dp[i][j]表示在区间i到j之间需要的最少的衣服数,当穿 j 这件衣服的时候,dp[i][j]=dp[i][j-1]+1,不穿的时候那肯定是之前也遇见过这个种类的衣服还穿在身上,那么就在i到j之间枚举k,当a[k]==a[j]的时候此时的dp[i][j]=min(dp[i][j],dp[i][k],dp[k+1][j])

    dp无非就是状态的转移,这里的就是穿不穿这件衣服这个状态,找出这两个选择后的状态发展。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 int min(int x,int y) {return x<y?x:y;}
     8 const int M = 100 + 10;
     9 int dp[M][M],a[M];
    10 
    11 int main()
    12 {
    13     int t,ans=0,n;
    14     scanf("%d",&t);
    15     while (t--){
    16         scanf("%d",&n);
    17         for (int i=1 ; i<=n ; i++) scanf("%d",&a[i]);
    18         for(int i=1;i<=n;i++)
    19             for(int j=i;j<=n;j++)
    20                 dp[i][j]=j-i+1;
    21         for (int i=n-1 ; i>=1 ; i--){
    22             for (int j=i+1 ; j<=n ; j++){
    23                 dp[i][j]=min(dp[i][j],dp[i][j-1]+1);
    24                 for (int k=i ; k<j ; k++){
    25                     if (a[j]==a[k])
    26                         dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);
    27                 }
    28             }
    29         }
    30         printf("Case %d: %d
    ",++ans,dp[1][n]);
    31     }
    32     return 0;
    33 }
    View Code
  • 相关阅读:
    [转]utf8编码原理详解
    [转]程序员趣味读物:谈谈Unicode编码
    confluence 安装部署
    统计日志10分钟内出现的次数
    Error occurred during initialization of VM Could not reserve enough space for object heap(可能是内核参数的问题)
    Linux服务器性能查看分析调优
    python break ,continue和 pass 语句(八)
    python 循环基础(六)
    python 循环实例(七)
    python 条件控制(五)
  • 原文地址:https://www.cnblogs.com/JJCHEHEDA/p/5656653.html
Copyright © 2020-2023  润新知