hiho 1271 舰队游戏 状压dp 贪心 模拟

来源:互联网 发布:影视飞飞cms 编辑:程序博客网 时间:2024/06/06 02:04

题目

题目链接:http://hihocoder.com/problemset/problem/1271

题目来源:hiho的比赛。

简要题意:给定对空和对舰的飞机还有一个航母,给定计算公式,要你弄个奇怪的方案。

题解

题意非常扭曲,但是的确算是个好题吧。

对于30%的数据,可以进行搜索,枚举每个位置放哪个飞机。

对于大数据可以采用状压dp的方式。

最多16个位置,状态空间为216

由于题目中的限制,你无法直接去算整个结果。

可以分别计算两边的最大值然后再进行一个最后的判断

dp[i][j]表示前i个对?飞机,位置使用状况为j的最大对?伤害。

搞完之后根据题目之中的条件进行一个判断就可以了。

需要注意的是如果直接这么做还是无法通过所有数据的。

可以发现任何位置对同种的伤害越大越好

于是可以排序,只留下最大的n×m个对空,对舰的然后去做。

开始直接搞,没贪心各种WA,TLE一晚上,第二天醒来就想明白了。

题目本身还是非常不错的,代码量还是有点长。

代码

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#include <queue>#include <string>#include <vector>#include <set>#include <map>#define fi first#define se secondusing namespace std;typedef long long LL;typedef pair<int,int> PII;typedef pair<LL,LL> PLL;// headconst int N = 10;const int T = 1005;const int M = 1 << 16;const int INF = -1;int a[N][N];vector<int> b, c;vector<PII> d;int dp[2][M];int res[2][M];bool exist = false;bool yes = false;int ans = 0;int n, m, t, s, tt, x, nm, mx;bool ck(int st) {    int temp[5];    memset(temp, 0, sizeof temp);    for (int i = 0; i < (n*m); i++) {        if ((1 << i) & st) {            temp[d[i].fi] = true;        }    }    for (int i = 0; i < n; i++) {        if (!temp[i]) return false;    }    return true;}void getRes(int *tar, const vector<int> &v) {    memset(dp, INF, sizeof dp);    dp[0][0] = 0;    int cur = 1, pre = 0;    for (int i = 0; i < v.size(); i++) {        for (int j = 0; j < mx; j++) {            if (dp[pre][j] == INF) continue;            dp[cur][j] = max(dp[cur][j], dp[pre][j]);            for (int k = 0; k < nm; k++) {                if ((1 << k) & j) continue;                int nxt = j | (1<<k);                dp[cur][nxt] = max(dp[cur][nxt], dp[pre][j] + a[d[k].fi][d[k].se] * v[i]);            }        }        swap(cur, pre);    }    memcpy(tar, dp[pre], sizeof dp[pre]);}void solve() {    getRes(res[0], b);    getRes(res[1], c);    for (int i = 0; i < mx; i++) {        if (res[0][i] < s) continue;        exist = true;        int cur = (mx-1) ^ i;        if (res[1][cur] < ans) continue;        if (res[1][cur] > ans) {            ans = res[1][cur];            yes = false;        }        if (ck(cur)) {            yes = true;        }    }}void input(vector<int> &b) {    for (int i = 0; i < t; i++) {        scanf("%d", &x);        if (x) b.push_back(x);    }    sort(b.begin(), b.end());    reverse(b.begin(), b.end());    while (b.size() > d.size()) {        b.pop_back();    }}int main() {    scanf("%d", &tt);    while (tt--) {        scanf("%d%d%d%d", &n, &m, &t, &s);        nm = n * m;        mx = 1 << nm;        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                scanf("%d", a[i]+j);                d.push_back(make_pair(i, j));            }        }        input(b);        input(c);        exist = yes = false;        ans = 0;        solve();        if (!exist) {            puts("Not Exist");        } else {            printf("%d\n%s\n", ans, (yes ? "Yes" : "No"));        }        d.clear();        b.clear();        c.clear();    }    return 0;}
0 0
原创粉丝点击