题目链接:https://nanti.jisuanke.com/t/38223
题意:有一堆火柴构成了一个加减法式子,你可以把火柴重新组合,要求数字个数和原来一样多,每个数字的位数和对应原数字位数一样多,总火柴数量也一样多,要求你构造新的式子算出来的结果最大。
思路:我们用dp[i][j]表示前i个数 用了j根火柴 所能达到的最大值 为此我们需要先预处理两个数组 mx[i][j] mn[i][j] 分别表示 i位数用了j根火柴的最大值/最小值
于是对于dp方程 我们可以得出 dp[i][j]=max(dp[i-1][j-p-2]+mx[b[i]][j],dp[i-1][j-p-1]+mn[b[i]][j]) 其中b[i]是第i个数字的位数 在dp方程中 我们考虑了+和-所带来的影响.
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define ll long long int using namespace std; inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1}; int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1}; const int inf=0x3f3f3f3f; const ll mod=1e9+7; ll mx[11][1007],mn[11][1007]; int a[10]={6,2,5,5,4,5,6,3,7,6}; //每个字符消耗的火柴数 ll dp[100][1000]; //前i个数字 用了j根火柴 int b[100]; //位数 void init(){ for(int i=0;i<11;i++) for(int j=0;j<1007;j++){ mx[i][j]=-1; //i位数 用j个火柴可以达到的最大值 mn[i][j]=1e17;//i位数 用j个火柴可以达到的最小值 } mx[0][0]=mn[0][0]=0; for(int i=1;i<11;i++) for(int j=0;j<=i*7;j++) for(int k=0;k<=9;k++){ if(j<a[k]) continue; mx[i][j]=max(mx[i][j],mx[i-1][j-a[k]]*10+k); //类似背包找最大值 mn[i][j]=min(mn[i][j],mn[i-1][j-a[k]]*10+k); } } int main(){ ios::sync_with_stdio(false); init(); int t; cin>>t; while(t--){ memset(dp,-1,sizeof(dp)); memset(b,0,sizeof(b)); int n; cin>>n; string s; cin>>s; int len=s.length(); int m=0; //火柴数 int k=1; //字符数 for(int i=0;i<len;i++){ if(s[i]=='+'){ k++; m+=2; }else if(s[i]=='-'){ k++; m++; }else{ m+=a[s[i]-'0']; b[k]++; } } for(int i=0;i<=m;i++) if(mx[b[1]][i]!=-1) dp[1][i]=mx[b[1]][i]; //初始化边界 for(int i=2;i<=k;i++) for(int j=0;j<=m;j++) for(int p=1;p<=700;p++){ if(j-p-2>=0&&dp[i-1][j-p-2]!=-1){ //考虑+号 if(mx[b[i]][p]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-p-2]+mx[b[i]][p]); } if(j-p-1>=0&&dp[i-1][j-p-1]!=-1){ //考虑-号 if(mn[b[i]][p]!=1e17) dp[i][j]=max(dp[i][j],dp[i-1][j-p-1]-mn[b[i]][p]); } } cout<<dp[k][m]<<endl; } return 0; }