那一步剪枝实在是没想到
#include<bits/stdc++.h> using namespace std; #define N 2005 struct Col{ int MAX,a[12],Max[1<<12]; }col[N]; int n,m,dp[15][1<<12]; int cmp(Col &a,Col &b){return a.MAX>b.MAX;} inline int judge(int s,int ss){ for(int i=0;i<12;i++) if(!(s>>i & 1) && (ss>>i & 1))return 0; return 1; } vector<int>v[1<<12]; void init(){ memset(dp,0,sizeof dp); memset(col,0,sizeof col); } int main(){ int t;cin>>t; for(int i=0;i<(1<<12);i++){ for(int j=0;j<=i;j++) if(judge(i,j)) v[i].push_back(j); } //for(auto ss:v[3])cout<<ss<<" "; while(t--){ init(); cin>>n>>m; for(int i=0;i<n;i++) for(int j=0;j<m;j++){ scanf("%d",&col[j].a[i]); col[j].MAX=max(col[j].MAX,col[j].a[i]); } sort(col,col+m,cmp); m=min(m,n);//只要用到最大值最大的前n列即可 for(int j=0;j<m;++j){ Col cur=col[j]; for(int p=0;p<n;++p) for(int s=0;s<(1<<n);++s){ int sum=0; for(int k=0;k<n;++k) if(s>>k & 1)sum+=cur.a[(p+k)%n]; col[j].Max[s]=max(col[j].Max[s],sum); } } for(int s=0;s<(1<<n);s++) dp[0][s]=col[0].Max[s]; for(int j=1;j<=m;j++){ for(int s=0;s<(1<<n);s++){ //for(int ss=0;ss<=s;ss++)if(judge(s,ss))//ss是s的子集 for(auto ss:v[s]){ //cout<<ss<<" "; dp[j][s]=max(dp[j][s],dp[j-1][s-ss]+col[j].Max[ss]); } //puts(""); } } cout<<dp[m][(1<<n)-1]<<' '; } }