考慮從前往後放所有輪。
如果上一輪是全中:
那麼這一輪如果是補中,一定放第一次最小的,這樣可以讓第一次大的放在其它補中之後。
如果這一輪是失誤,那麼一定放總分最大的。
如果上一輪是補中:
這一輪一定放第一次最大的。
所以每次要麼放補中裡第一次最小的,要麼放補中裡第一次最大的。
最優解中一定是全中補中先交替放,直到一方不足,然後按照剩下那一放對失誤輪進行貪心。
因為最後第二輪的限制,最後一輪可能是個特例,因此列舉哪輪失誤是特例,再列舉失誤輪貪心策略是按照總分還是第一次從大到小取,然後DP求最優解。
將補中按照第一次得分排序,設$f[i][l][r][j][k][o]$表示已經放了$i$個全中,還沒放的補中是區間$[l,r]$,已經放了前$j$個非特例失誤輪,特例有沒有放為$k$,目前最後放的那輪是全中/補中/失誤時的最優解。
時間複雜度$O(n^5)$,常數很小。
#include<cstdio> #include<algorithm> using namespace std; const int N=53; int n,flag,i,j,_,ca,cb,cc,cd,ans,f[N][N][N][N][2][3]; struct P{int x,y,z;}a[N],b[N],c[N],d,_c[N]; inline bool cmpx(const P&a,const P&b){return a.x>b.x;} inline bool cmpz(const P&a,const P&b){return a.z>b.z;} inline void up(int&a,int b){a<b?(a=b):0;} void solve(){ int i,j,r,k,S,o,w,v,t,x,y,cana,cane; for(i=0;i<=ca;i++)for(j=0;j<=cb;j++)for(r=cb;r>=j;r--)for(k=0;k<=cc;k++)for(S=0;S<=cd;S++)for(o=0;o<3;o++)f[i][j][r][k][S][o]=-1; f[0][0][cb][0][0][0]=0; for(i=0;i<=ca;i++)for(j=0;j<=cb;j++)for(r=cb;r>=j;r--)for(k=0;k<=cc;k++)for(S=0;S<=cd;S++)for(o=0;o<3;o++){ w=f[i][j][r][k][S][o]; if(w<0)continue; cana=cane=1; if(i+j+cb-r+k+S+1==n-1)cana=flag,cane=flag^1; if(cana&&i<ca){ t=10; if(o)t<<=1; up(f[i+1][j][r][k][S][1],w+t); } if(!cane)continue; if(j<r){ x=b[j+1].x,y=b[j+1].y; t=x+y; if(o==1)t=(x+y)<<1; if(o==2)t=(x<<1)+y; up(f[i][j+1][r][k][S][2],w+t); x=b[r].x,y=b[r].y; t=x+y; if(o==1)t=(x+y)<<1; if(o==2)t=(x<<1)+y; up(f[i][j][r-1][k][S][2],w+t); } if(k<cc){ x=c[k+1].x,y=c[k+1].y; t=x+y; if(o==1)t=(x+y)<<1; if(o==2)t=(x<<1)+y; up(f[i][j][r][k+1][S][0],w+t); } if(S<cd){ x=d.x,y=d.y; t=x+y; if(o==1)t=(x+y)<<1; if(o==2)t=(x<<1)+y; up(f[i][j][r][k][1][0],w+t); } } for(j=0;j<=cb;j++)for(o=0;o<3;o++)up(ans,f[ca][j][j][cc][cd][o]); } void cal(){ sort(c+1,c+cc+1,cmpz); solve(); sort(c+1,c+cc+1,cmpx); solve(); } int main(){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].y); a[i].z=a[i].x+a[i].y; } if(a[n].x==10){ n++; flag=1; scanf("%d%d",&a[n].x,&a[n].y); a[n].z=a[n].x+a[n].y; } for(i=1;i<=n;i++){ if(a[i].x==10){ca++;continue;} if(a[i].z==10){b[++cb]=a[i];continue;} c[++cc]=a[i]; } sort(b+1,b+cb+1,cmpx); cal(); for(i=1;i<=cc;i++){ cd=1,d=c[i]; for(j=1;j<=cc;j++)_c[j]=c[j]; for(_=0,j=1;j<=cc;j++)if(j!=i)c[++_]=c[j]; cc=_; cal(); for(cc++,j=1;j<=cc;j++)c[j]=_c[j]; } return printf("%d",ans),0; }