预处理+状态压缩+剪枝——codefoece 1209E

那一步剪枝实在是没想到

#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]<<'
';
    }        
}            
原文地址:https://www.cnblogs.com/zsben991126/p/11623778.html