https://codeforces.com/contest/1209/problem/E2
给出$n$行和$m$列
每次操作循环挪动某列一次
可以执行无数次这样的操作
让每行最大值的累加和最大
$1\leq n \leq 12$
$1\leq m \leq 20000$
定义$dp[i][j]$,考虑前$i$列,选择状态为$j$的最大值
$ans=dp[m][(1<<n)-1]$
$dp[i][j]$可以由$dp[i-1][k]$转移,$k$是$j$的二进制子集
$easy$难度还是比较好写的
$hard$难度需要预处理,和保留最多$n$列
const int N=5; const int M=105; int n,m,B[M],A[N][M]; int f[1<<N][M]; int main( ) { int i,j,k,t,z,r,u,G,T=read( ); while(T--) { read(n); read(m);; for(i=1; i<=n; i++) for(j=1; j<=m; j++) A[i][j]=read( ); int S=(1<<n)-1; for(i=1; i<=m; i++) for(j=0; j<=S; j++) f[j][i]=0; for(i=1; i<=m; i++) { for(j=0; j<=S; j++) { for(k=j;; k=(k-1)&j) { u=0; for(t=0; t<n; t++) { r=0; for(z=1; z<=n; z++) { G=((z-1)+t)%n+1; if(((1<<(G-1))&j)&&(!((1<<(G-1))&k))) r+=A[z][i]; } u=max(u,r); } f[j][i]=max(f[j][i],f[k][i-1]+u); if(!k) break; } } } printf("%d\n",f[S][n]); } return 0; }
#include<bits/stdc++.h> #define ll long long #define pii pair<int,int> using namespace std; const int maxn=12+10; const int maxm=2007; int num[maxn][maxm]; pii p[maxn*maxm]; int lis[maxn][maxn],cnt; int dp[maxn][(1<<12)+10],f[maxn][(1<<12)+10]; set<int>se; int main() { int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&num[i][j]); p[(i-1)*m+j]=make_pair(num[i][j],j); } } sort(p+1,p+1+n*m); se.clear(); for(int i=0;i<n*m;i++){ se.insert(p[n*m-i].second); if(se.size()==n)break;//保留最多n列 } int cnt=0; for(auto i:se){ cnt++; for(int j=1;j<=n;j++) lis[j][cnt]=num[j][i]; } m=cnt; int len=(1<<n); memset(f,0,sizeof(f)); for(int i=1;i<=m;i++)//预处理每列选择状态的最优解 for(int choose=0;choose<len;choose++){ for(int j=1;j<=n;j++){ int res=0; for(int k=1;k<=n;k++){ int g=(k-1+j)%n+1; if((1<<(g-1))&choose)res+=lis[k][i]; } f[i][choose]=max(res,f[i][choose]); } } memset(dp,0,sizeof(dp)); for(int i=1;i<=m;i++){ for(int choose=0;choose<len;choose++){ for(int shift=choose;;shift=((shift-1)&choose)){//枚举choose的子集 int v=choose-(shift&choose); dp[i][choose]=max(dp[i][choose],dp[i-1][shift]+f[i][v]); if(shift==0)break; } } } printf("%d\n",dp[m][len-1]); } return 0; }
codeforces#1290E2 - Rotate Columns (hard version)(子集dp)
原文:https://www.cnblogs.com/carcar/p/11544541.html