题解:
dp
dp[i][j]表示i个红,j个绿的最小代价
然后再加上两位k,l,表示k个红连,l个绿连
然后转移
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1005; const ll INF=1LL<<50; ll a[N],b[N],f[N][N][3][3],j,k,n,m,tot1,tot2; int main() { scanf("%d%d",&m,&n); for (int i=1;i<=n;i++) { scanf("%d%d",&k,&j); if (j)a[++tot1]=k; else b[++tot2]=k; } sort(a+1,a+1+tot1); sort(b+1,b+1+tot2); for (int i=tot1+1;i<=n;i++)a[i]=INF; for (int i=tot2+1;i<=n;i++)b[i]=INF; for (int i=0;i<=m;i++) for (int j=0;j<=n;j++) for (int t=0;t<=2;t++) for (int l=0;l<=2;l++)f[i][j][t][l]=INF; f[0][0][0][0]=0; int ad,bd; for (int i=1;i<=m;i++) { for (int j=1,ad=a[j]*(m-i+1),bd=b[i-j]*(m-i+1);j<=i;j++, ad=a[j]*(m-i+1),bd=b[i-j]*(m-i+1)) { f[i][j][1][0]=min(f[i-1][j-1][0][0], min(f[i-1][j-1][0][1],f[i-1][j-1][0][2]))+ad; f[i][j][2][0]=f[i-1][j-1][1][0]+ad; f[i][j][0][1]=min(f[i-1][j][0][0], min(f[i-1][j][1][0],f[i-1][j][2][0]))+bd; f[i][j][0][2]=f[i-1][j][0][1]+bd; } bd=b[i]*(m-i+1); f[i][0][0][1]=min(f[i-1][0][0][0],min(f[i-1][0][1][0],f[i-1][0][2][0]))+bd; f[i][0][0][2]=f[i-1][0][0][1]+bd; } ll ans=INF; for (int i=0;i<=tot1;i++) { ans=min(ans,f[m][i][0][0]); ans=min(ans,f[m][i][0][1]); ans=min(ans,f[m][i][0][2]); ans=min(ans,f[m][i][1][0]); ans=min(ans,f[m][i][2][0]); } printf("%lld\n",ans); return 0; }