bzoj4922 [Lydsy1706月賽]Karp-de-Chant Number 貪心+dp
阿新 • • 發佈:2018-12-28
中文題自己看。
可以想到揹包,然後用:先放會使累計的左括號增加的,最後放會使累計的左括號減少的,先放的是按最大括號深度從小到大,後放的是按不計算被該塊右括號消去的增加的左括號從大到小,按這個順序排個序,就可以做消去限制的揹包了。
AC Code:
#define maxn 305 using namespace std; int n,a[maxn],b[maxn],c[maxn],ct[maxn],tp[maxn]; inline bool cmp(const int u,const int v) { if(tp[u]!=tp[v]) return tp[u] < tp[v]; if(tp[u]==0) return a[u] < a[v]; else return b[u] > b[v]; } int dp[2][maxn*maxn+500]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { char ch[305]; cin>>ch; int len = strlen(ch); for(int j=0;j<len;j++) { if(ch[j] == ')') { if(b[i]) b[i]--,ct[i]+=2; else a[i]++; } else b[i] ++; } c[i]=i; if(a[i] < b[i]) tp[i] = 0; else tp[i] = 1; } sort(c+1,c+1+n,cmp); memset(dp,-0x3f,sizeof dp); int now=1,pre=0; dp[pre][0] = 0; for(int i=1;i<=n;i++,swap(now,pre)) { for(int j=90000;j>=0;j--) dp[now][j] = dp[pre][j]; for(int j=90000;j>=a[c[i]];j--) if(dp[pre][j] >= 0) dp[now][j+b[c[i]]-a[c[i]]] = max(dp[now][j+b[c[i]]-a[c[i]]] , dp[pre][j] + 2*a[c[i]] + ct[c[i]]); } printf("%d\n",max(0,dp[pre][0])); }