zoukankan      html  css  js  c++  java
  • 【补题】牛客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 }

    追求吾之所爱
  • 相关阅读:
    【leetcode】Pascal's Triangle
    [bxd学习java基本点]10.set元素不重复,取元素顺序会变的。TreeSet取值时,是安顺序来的。
    cocos2dx 学习点滴(4) cocos2dx 架构和引擎目录
    VC 2008编译libxml22.7.6
    程序猿的九重天
    使用批处理文件设置环境变量
    删除指定目录下除开指定文件外所有文件的批处理命令
    关于永动机的思考
    程序员的九阳真经
    上帝的归上帝,程序的归程序 (卓有成效的程序员)
  • 原文地址:https://www.cnblogs.com/rstz/p/12382565.html
Copyright © 2011-2022 走看看