二进制枚举参见:https://blog.csdn.net/sugarbliss/article/details/81099340
位运算:https://baike.baidu.com/item/%E4%BD%8D%E8%BF%90%E7%AE%97
本题:数据太水,假算法也能过。
先上一个我都不知到为能过得算法:
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 constexpr size_t maxn = 15 + 1; 5 int h[maxn], l[maxn]; 6 int mp[maxn][maxn]; 7 int main(){ 8 int n, m, k, s = 0; 9 cin >> n >> m >> k; 10 for(int i = 1; i <= n; ++ i){ 11 for(int j = 1; j <= m; ++ j){ 12 int a; 13 cin >> a; 14 mp[i][j] = a; 15 h[i] += a; 16 l[j] += a; 17 s += a; 18 } 19 } 20 if(k >= n || k >= m){ 21 cout << s << endl; 22 return 0; 23 } 24 int ans1 = 0, ans2 = 0; 25 sort(h + 1, h + n + 1,greater<int>()); 26 sort(l + 1, l + m + 1,greater<int>()); 27 for(int i = 1; i <= k; ++ i){ 28 ans1 += h[i]; 29 ans2 += l[i]; 30 } 31 cout << max(ans1, ans2) << endl; 32 return 0;
接下来就是标程啦;
我们枚举每一行或者每一列都可以啦。
先说明:二进制枚举状态有2^n-1, 也就是(1 << n ) – 1;自己可以用数学归纳法看看。
其中1表示选了这一行,0表示没选这一行。
先上臭妹妹代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int num[20][20],hang[20],lie[20]; 4 int main() 5 { 6 ios::sync_with_stdio(false); 7 cin.tie(0);cout.tie(0); 8 int n,m,k,sum=0,ans=0; 9 cin>>n>>m>>k; 10 for(int i=0;i<n;i++){ 11 for(int j=0;j<m;j++){ 12 cin>>num[i][j]; 13 hang[i]+=num[i][j]; 14 lie[j]+=num[i][j]; 15 sum+=num[i][j]; 16 } 17 } 18 if(k>n || k>m){ 19 cout<<sum<<endl; 20 }else{ 21 for(int pick=0;pick<(1<<n);pick++){ 22 int cont=0;sum=0; 23 vector<int>li; 24 for(int i=0;i<m;i++){ 25 li.push_back(lie[i]); 26 } 27 28 for(int i=0;i<n;i++){ 29 if((pick>>i)&1){ 30 cont++; 31 sum+=hang[i]; 32 for(int j=0;j<m;j++){ 33 li[j]-=num[i][j]; 34 } 35 } 36 } 37 if(cont>k) continue; 38 int another_cont=k-cont; 39 sort(li.begin(),li.end(),[](const int &a,const int &b){return a>b;}); 40 for(int i=0;i<another_cont;i++){ 41 sum+=li[i]; 42 } 43 ans=max(ans,sum); 44 } 45 cout<<ans<<endl; 46 } 47 return 0; 48 }
我的代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 constexpr size_t maxn = 16; 8 int mp[maxn][maxn]; 9 vector<int>row(16, 0); 10 vector<int>col(16, 0); 11 int s = 0, ans = 0; 12 13 int main(){ 14 int n, m, k; 15 cin >> n >> m >> k; 16 17 for(int i = 1; i <= n; ++ i){ 18 for(int j = 1; j <= m; ++ j){ 19 int a; 20 cin >> a; 21 mp[i][j] = a; 22 row[j] += a; 23 col[i] += a; 24 s += a; 25 } 26 } 27 if(k >= m || k >= n){ 28 cout << s << endl; 29 return 0; 30 } 31 32 for(int i = 0; i < (1 << n); ++ i){ 33 int cnt = k, ans1 = 0; 34 vector<int>row1(row);//将row赋值给row1 35 for(int j = 0; j < n; ++ j){ 36 37 if(i & (1 << j)){//如果当前位为1,表示要取 38 cnt --; 39 ans1 += col[j + 1]; 40 for(int l = 1; l <= m; ++ l){//减去对应列的值 41 row1[l] -= mp[j + 1][l]; 42 } 43 if(cnt == 0) 44 break; 45 } 46 } 47 sort(row1.begin(),row1.end(),[](const int &a, const int &b){ 48 return a > b; 49 });//这是一个朴树得贪心思想 50 for(int j = 0; j < cnt; ++ j){//如果cnt还有就选列 51 ans1 += row1[j]; 52 } 53 ans = max(ans1, ans); 54 } 55 cout << ans << endl; 56 return 0; 57 }