1 条题解

  • 1
    @ 2025-5-6 20:27:03

    暴力,二进制枚举。

    对于每种指标,将他的绝对值展开,都只有两种情况:

    $$|x_i(\mathrm{MW}) - x_i(\mathrm{SW})| = \begin{cases} +x_i(\mathrm{MW}) - x_i(\mathrm{SW}), & x_i(\mathrm{MW}) \ge x_i(\mathrm{SW}), \\[6pt] +x_i(\mathrm{SW}) - x_i(\mathrm{MW}), & x_i(\mathrm{MW}) < x_i(\mathrm{SW}). \end{cases} $$

    也就是说,对于主武器和副武器的每一个指标,他对答案的贡献要么是++,要么是-,并且这两个的符号恰恰相反。

    那一共有kk种指标,每种指标有加和减两种情况,是不是恰好可以用二进制的0011来表示?一共有2k2^k种情况,每种情况可以用一个kk位的二进制数来表示,maskmask11遍历到2k2^k就可以枚举所有的情况,maskmaskii位为11就让主武器减、副武器加。第ii位为00就让主武器加、副武器减,对于每个maskmask,分别遍历一遍所有的主副武器,分别找到对答案贡献最大的,所有情况取maxmax即可。

    二进制枚举的过程也可以通过dfsdfs指数级枚举来实现。

    时间复杂度:O((n+m)×2k)O(\sum(n +m) \times 2^k )

    ACcode1

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define endl '\n'
    using namespace std;
    using LL = long long;
    
    struct Wea{
    	int s;
    	int x[6];
    };
    
    void solve(){
    	int n, m, k;
    	cin >> n >> m >> k;
    	vector<Wea> a(n), b(m);
    	for(int i = 0; i < n; i++){
    		cin >> a[i].s;
    		for(int j = 0; j < k; j++){
    			cin >> a[i].x[j];
    		}
    	}
    	for(int i = 0; i < m; i++){
    		cin >> b[i].s;
    		for(int j = 0; j < k; j++){
    			cin >> b[i].x[j];
    		}
    	}
    	LL res = -1e18;
    	for(int mask = 0; mask < (1 << k); mask++){
    		LL max1 = -1e18;
    		for(int i = 0; i < n; i++){
    			LL sum = a[i].s;
    			for(int j = 0; j < k; j++){
    				if(mask >> j & 1) sum -= a[i].x[j];
    				else sum += a[i].x[j];	
    			}
    			max1 = max(max1, sum);
    		}
    		LL max2 = -1e18;
    		for(int i = 0; i < m; i++){
    			LL sum = b[i].s;
    			for(int j = 0; j < k; j++){
    				if(mask >> j & 1) sum += b[i].x[j];
    				else sum -= b[i].x[j];
    			}
    			max2 = max(max2, sum);
    		}
    		res = max(res, max1 + max2);
    	}
    	cout << res << endl;
    }
    
    int main(){
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	int T;
    	cin >> T;
    	while(T--){
    		solve();
    	}
    	return 0;
    }
    

    ACcode2

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <climits>
    #define endl '\n'
    using namespace std;
    using LL = long long;
    
    struct Wea{
        int s;
        int x[6];
    };
    
    int n, m, k;
    vector<Wea> a, b;
    vector<int> bit;
    LL res;
    
    void dfs(int pos){
        if(pos == k){
            LL max1 = -1e18;
            for(int i = 0; i < n; i++){
                LL sum = a[i].s;
                for(int j = 0; j < k; j++){
                    if(bit[j]) sum -= a[i].x[j];
                    else sum += a[i].x[j];
                }
                max1 = max(max1, sum);
            }
            LL max2 = -1e18;
            for(int i = 0; i < m; i++){
                LL sum = b[i].s;
                for(int j = 0; j < k; j++){
                    if(bit[j]) sum += b[i].x[j];
                    else sum -= b[i].x[j];
                }
                max2 = max(max2, sum);
            }
            res = max(res, max1 + max2);
            return;
        }
        bit[pos] = 0;
        dfs(pos + 1);
        bit[pos] = 1;
        dfs(pos + 1);
    }
    
    void solve(){
        cin >> n >> m >> k;
        a.resize(n);
        b.resize(m);
        for(int i = 0; i < n; i++){
            cin >> a[i].s;
            for(int j = 0; j < k; j++) cin >> a[i].x[j];
        }
        for(int i = 0; i < m; i++){
            cin >> b[i].s;
            for(int j = 0; j < k; j++) cin >> b[i].x[j];
        }
        bit.assign(k, 0);
        res = -1e18;
        dfs(0);
        cout << res << endl;
    }
    
    int main(){
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int T;
        cin >> T;
        while(T--){
            solve();
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    2277
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    8
    已通过
    2
    上传者