1. 程式人生 > >ICPC China Nanchang National Invitational -- D. Match Stick Game(dp)

ICPC China Nanchang National Invitational -- D. Match Stick Game(dp)

邊界 false tor gcd ace blank tar -- max

題目鏈接: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; }

ICPC China Nanchang National Invitational -- D. Match Stick Game(dp)