题意:
n行∗m列≤16个空位,每个空位有个权值ai,b物品权值bi,c物品权值ci
每个空位只能放置一个物品,且物品贡献为ai∗bj或者ai∗cj
现要求满足a物品贡献≥s的情况下,最大的c物品贡献,不满足输出“Not Exist”
否则输出最大的c物品贡献,且如果每行有至少有一个c物品输出“Yes”,否则“No”
分析:
虽然物品很多,但其实有用的是最大的那几个
先给a排个降序,16这个数,显然二进制枚举,枚举后就可以贪心了,a大的乘b,c大的
枚举b物品的放置情况,由于a已经降序,显然b也从大到小选
剩下的肯定按照a从大到小放c,自然是能放多少是多少,也从大到小
注意物品个数的边界情况,问题解决
时间复杂度O(nm∗2nm)
代码:
//
// Created by TaoSama on 2016-03-06
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m, t, s;
int a[16], r[16];
bool cmp(int x, int y) {
return a[x] > a[y];
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int q; scanf("%d", &q);
while(q--) {
scanf("%d%d%d%d", &n, &m, &t, &s);
int nm = n * m;
for(int i = 0; i < nm; ++i) scanf("%d", a + i), r[i] = i;
sort(r, r + nm, cmp);
vector<int> air, ship;
for(int i = 1; i <= t; ++i) {
int x; scanf("%d", &x);
if(x) air.push_back(x);
}
for(int i = 1; i <= t; ++i) {
int x; scanf("%d", &x);
if(x) ship.push_back(x);
}
sort(air.begin(), air.end(), greater<int>());
sort(ship.begin(), ship.end(), greater<int>());
int maxAtk = -INF, yes = 0;
for(int mask = 0; mask < 1 << nm; ++mask) {
int f, g, each, d, atk;
f = g = each = d = atk = 0;
for(int i = 0; i < nm; ++i) {
if(mask >> i & 1) {
if(f < air.size()) d += a[r[i]] * air[f++];
} else {
if(g < ship.size()) {
atk += a[r[i]] * ship[g++];
each |= 1 << (r[i] / m);
}
}
}
each = each == (1 << n) - 1;
if(d >= s) {
if(atk > maxAtk) {
maxAtk = atk;
yes = each;
} else if(atk == maxAtk) yes |= each;
}
}
if(maxAtk != -INF) {
printf("%d\n", maxAtk);
puts(yes ? "Yes" : "No");
} else puts("Not Exist");
}
return 0;
}