CF1239E Turtle
通过观察我们会发现,第一行一定单调递增,第二行一定单调递减,否则不是最优。再次前提下,乌龟的最优方案只有两种,要么一直向右,最后向下,要么先向下,再一直向右。因此,我们将最小的两个数字放在左上角和右下角,然后把余下数字填入剩余位置,并希望下式最小
显然,这是一个背包问题。
设f[i][j][k]表示前i件物品,取j件,和为k的方案是否存在
f[i][j][k]=f[i-1][j][k]|f[i-1][j-1][k-ai]
从sum/2到0,枚举k,若f【n*2】【n-1】【k】==1,则方案合法,且最大值最小。
#include<bits/stdc++.h> using namespace std; const int N=1300000; bitset<N> dp[53][27]; int a[55],b[N],n,m,sum; void print(int n,int m,int i){ if(!m) return; if(dp[n-1][m][i]){ print(n-1,m,i); return; } if(i>=a[n]){ if(dp[n-1][m-1][i-a[n]]){ b[a[n]]--; print(n-1,m-1,i-a[n]); printf("%d ",a[n]); } } } int main(){ cin>>n; m=n<<1; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) cin>>a[i+n]; sort(a+1,a+1+m); for(int i=3;i<=m;i++){ sum+=a[i],b[a[i]]++; } int tmp=sum; sum/=2; dp[2][0]=1;//从第三个开始选 for(int i=3;i<=m;i++){//i个数中,选j个数到a for(int j=0;j<=n-1;j++){ dp[i][j]|=dp[i-1][j]; if(j) dp[i][j]|=dp[i-1][j-1]<<a[i]; //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; } } for(int i=sum;i>=0;i--){ if(dp[m][n-1][i]){ cout<<a[1]<<" "; print(m,n-1,i); cout<<endl; for(int j=50005;j>=0;j--){ while(b[j]){ b[j]--; printf("%d ",j); } } cout<<a[2]<<endl; return 0; } } return 0; }
但是,这么写空间可能会爆,因此我们考虑用bitset优化dp,具体细节见代码
最后我们要输出具体方案,因此不能使用滚动数组,需要在最后递归输出。
标签:Turtle,int,CF1239E,--,print,dp From: https://www.cnblogs.com/DongPD/p/17493235.html