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