/* p个位置用来组队(有序) k个观众(无序) 要求收益最大化,dp[i][S]表示前i个人的组队状态是S时的最大收益 先对a进行排序 第i个人加入后有三种选择: 找个位置组队: 挑一个S中为0的位置 不组队,去当观众/有可能当不成:如果i-cnt(S)>=k,那么当不成观众 */ #include<bits/stdc++.h> using namespace std; #define N 200005 #define ll long long struct Node{ ll a,s[7]; }b[N]; int cmp(Node &a,Node &b){return a.a>b.a;} ll n,p,k,dp[N][1<<7],cnt[1<<7]; void prework(){ for(int i=0;i<(1<<7);i++){ int res=0; for(int j=0;j<7;j++) if(i>>j & 1)res++; cnt[i]=res; } } int main(){ prework(); cin>>n>>p>>k; for(int i=1;i<=n;i++)scanf("%lld",&b[i].a); for(int i=1;i<=n;i++) for(int j=0;j<p;j++)scanf("%lld",&b[i].s[j]); sort(b+1,b+1+n,cmp); memset(dp,-1,sizeof dp); dp[0][0]=0; for(int i=0;i<n;i++){ for(int S=(1<<p)-1;S>=0;S--)if(dp[i][S]!=-1){ //不组队 if(i-cnt[S]>=k)dp[i+1][S]=max(dp[i+1][S],dp[i][S]); else dp[i+1][S]=max(dp[i+1][S],dp[i][S]+b[i+1].a); //组队 for(int j=0;j<p;j++)if(!(S>>j & 1)) dp[i+1][S|(1<<j)]=max(dp[i+1][S|(1<<j)],dp[i][S]+b[i+1].s[j]); } } cout<<dp[n][(1<<p)-1]<<' '; }