• 题解——碰杯


    题目描述

    今天的酒席有n个人,他们要同时举杯,成对碰杯。碰杯的时候,不能有人不参与碰杯,也不希望有手臂交叉这种别扭的情况出现每个人都有一个喜爱的酒种类,每个人想要与和自己喝一样酒的人碰杯,请你设计一个方法,在保证每个人参与碰杯,且没有手臂交叉的情况下,有最多的人与喝一样酒的人碰杯,输出最多有多少人能与喝一样酒的人碰杯。

    输入输出

    第一行一个数n,表示酒桌上人的个数。
    第二行n个数ci,逆时针方向依次表示坐在第i个位置的人喝哪种酒,第1个和第n个人是相邻的。

    样例

    【输入样例1】
    6
    1 2 2 1 3 3
    【输出样例1】
    3

    对于这道题目,显然可以看出是一道区间Dp,但是如何进行合法的区间合并,是本题的关键。
    没有手臂交叉,就是在进行区间合并时不能将合法的分割点所分成的左右区间中进行统计匹配。那么,这就需要我们合并区间时做一些修改。
    我们来分析下面这组数据:
    现定义2个合法区间 dp[i~k-1] 和 dp[k+1~j-1]。如果分割点为 K ,末端点为 j , 我们保证 dp[i~k] 和 dp[k~j] 中没有人交叉碰杯,那么只需要将 k , j 提出在进行合并即可。 该方法正确性显然。

    所以我们得到转移方程

      ( c[ j ] == c[ k ] )dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i ][ k - 1 ] + dp[ k+1 ][ j - 1 ] + 1 );
      ( c[ j ] != c[ k ] )dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i ][ k - 1 ] + dp[ k+1 ][ j - 1 ] );
    

    那么,本题就差一个区间Dp的框架了。

    AC代码

    **注:本题可以不开 long long **

    #include<bits/stdc++.h>
    using namespace std;
    #define  ll long long 
    ll dp[ 1005 ][ 1005 ] , ans , N , c[ 1005 ] ;
    inline ll read()
    {
        ll s = 0,w = 1;
        char g = getchar();
        while(g<'0'||g>'9'){if(g=='-')w*=-1;g = getchar();}
        while(g>='0'&&g<='9'){s = s*10+g-'0';g = getchar();}
        return s*w;
    }
    void  init_(){
    	freopen("toasting.in","r",stdin);
    	freopen("toasting.out","w",stdout);
    }
    void  prepare_(){
    	N = read() ;  memset( dp , 0 , sizeof(dp) ) ;
    	for( register int  i = 1 ; i <= N ; i ++ )c[ i ]  = read() ; 
    }
    void  Dp_(){
    	for( register int  j = 2 ; j <= N ; j++ )
    		for( register int i = j - 1 ; i >= 1 ; i -= 2 )
                for( register int k = i ; k <= j - 1 ; k += 2 ){ // compared c[ i ] with c[ k ] , so we need add dp i,k-1  k+1,j-1 
                	if( c[ j ] == c[ k ] )dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i ][ k - 1 ] + dp[ k+1 ][ j - 1 ] + 1 );
                	else  dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i ][ k - 1 ] + dp[ k+1 ][ j - 1 ] );
    		}
    }
    void  Find_ans(){
    	cout<< dp[ 1 ][ N ] <<endl;
    }
    int  main()
    {
    	init_();
    	prepare_() ;
    	Dp_() ;
    	Find_ans();
    	return  0 ;
    }
    
    相信下一次有人看这篇博客也是我退役的时候了。

    有疑惑和建议,可以留下评论或私我。

    如果你喜欢我的文章,请点赞支持,谢谢。

  • 相关阅读:
    vux 局部注册组件
    vux 全局注册组件
    axios请求本地json
    vux报错 this指针问题
    Vue如何引入远程JS文件
    报错 ERROR in static/js/vendor.b3f56e9e0cd56988d890.js from UglifyJs
    封装axios
    js判断手机型号
    js判断是否在微信浏览器打开
    nginx+tomcat实现负载均衡以及session共享(linux centos7环境)
  • 原文地址:https://www.cnblogs.com/ssw02/p/10848498.html
Copyright © 2020-2023  润新知