【补题】牛客58矩阵消除【数据水的一匹,算法:二进制枚举】


二进制枚举参见:https://blog.csdn.net/sugarbliss/article/details/81099340

位运算:https://baike.baidu.com/item/%E4%BD%8D%E8%BF%90%E7%AE%97

XTMEK]~HJ`KOC~Q81XEV2AD


本题:数据太水,假算法也能过。

先上一个我都不知到为能过得算法:

  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 }

猜你喜欢

转载自www.cnblogs.com/rstz/p/12382565.html
今日推荐