20161020测试T1 解题报告(7)——Hello

Hello

算法分析:

方法一: 直接暴力搜索 期望得分:  30~40

时间复杂度:n!(怎么都是死)

1)读入字符串,分离各位置;

2)从第一位开始传参搜索每一种可能;

 

Source:

#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
          #include 
         
           using namespace std; long long w[40],n; /*w:分离后的数字*/ long long maxx; /*maxx:求解最大值*/ string s; void dfs(int cnt,long long sum1,long long sum2,int num1,int num2) /*强行搜索; cnt:位数; sum1:A当前数据; sum2:B当前数据*/ /*num1:A当前已选择的个数; num2:B当前已选择的个数*/ { if(cnt>(n<<1)) /*得到一种方案,更新*/ { if(sum1+sum2>maxx) { maxx=sum1+sum2; } } if(num1 
          
            >n; cin>>s; divide(s); /*分离*/ dfs(1,0,0,0,0); /*搜索*/ cout< 
            
           
          
        
       
       
      
      
     
     
    
    

 

方法二:贪心(无正确性) 期望得分:90

时间复杂度:n

1)读入字符串,分离各位置;

2)从第一位开始,第一个数据的当前数字,取开头的第一个,第二个数字取,保证足够位数的前提下的最大值;

3)乘以当前的位数的倍数;

 

Source:


#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         
#include
         
         
          
          
#include
          
          
            #include 
           
             using namespace std; const long long digist[19]= {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,1000000000000000000}; /*digist:乘方打表*/ int w[40],n; /*w:分离位数*/ long long ans; /*ans:答案记录*/ bool num[40]; /*num:记录当前数是否已经被取用*/ int del[2][40]; /*del:记录两个数字的每一位*/ int maxx,maxd; /*maxx:临时记录最大值; maxd:临时记录最大值所在编号*/ string s; inline void R(int &v) /*读入优化*/ { char c=0; bool p=true; v=0; while(c<'0'||c>'9') { if(c=='-') { p=false; } c=getchar(); } while(c>='0'&&c<='9') { v=(v<<3)+(v<<1)+(c^'0'); c=getchar(); } if(p==false) { v=-v; } } void divide(string s) /*分离位数*/ { for(int i=0;i 
            
              >n; cin>>s; divide(s); work(); return 0; } 
             
            
          
         
         
        
        
       
       
      
      

方法三:动态规划(正解) 期望得分:100 

时间复杂度:n2

1)读入字符串,分离各位置;

2)动态规划dp[i][j]表示A还有i个数未取用,B还有j个数未取用。【状态转移:dp[i][j]=max(dp[i-1][j]+w[2*n-i-j]*digist[i],dp[i][j-1]+w[2*n-i-j]*digist[j])

3)输出答案为dp[0][0];

 

Source:

#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         
#include
         
         
          
          
#include
          
          
            #include 
           
             using namespace std; const long long digist[19]= {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,1000000000000000000}; /*digist:乘方打表*/ int w[40],n; /*w:分离位数*/ long long dp[20][20]; /*dp:动归记录*/ string s; inline void R(int &v) /*读入优化*/ { char c=0; bool p=true; v=0; while(c<'0'||c>'9') { if(c=='-') { p=false; } c=getchar(); } while(c>='0'&&c<='9') { v=(v<<3)+(v<<1)+(c^'0'); c=getchar(); } if(p==false) { v=-v; } } void divide(string s) /*分离位数*/ { for(int i=0;i 
            
              =0;--i) /*状态初始化*/ { dp[n][i]=dp[n][i+1]+w[n-i]*digist[i]; dp[i][n]=dp[i+1][n]+w[n-i]*digist[i]; } for(int i=n-1;i>=0;--i) /*动归开始*/ { for(int j=n-1;j>=0;--j) { dp[i][j]=max(dp[i+1][j]+w[2*n-i-j]*digist[i],dp[i][j+1]+w[2*n-i-j]*digist[j]); } } cout< 
             
               >n; cin>>s; divide(s); work(); return 0; } 
              
             
            
          
         
         
        
        
       
       
      
      


 Summary:

本题其实真心不算难,但是只会写搜索的我就只得了暴力分而已······表示动归不行是硬伤······本题其实经过思考,动归方程是很明显的,而且其实有很多方法,比如说贪心是可以得到很多分值的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值