• 1625 夹克爷发红包 贪心 + 暴力 + 思维


    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1625&judgeId=203076

    一开始的时候,还想着枚举每一行的总和,和每一列的总和,然后选一个最小的来变就好。

    然后wa了,只剩下一组数据,然后看到还是大数据,调试不了。

    然后上网搜,然后跪了。

    我那种做法应该是有后效性的。数据在下面

    3 3 30 2
    10 10 10
    1 1 99
    20 20 99

    不知道怎么描述这种情况,应该就算是一个二维贪心的反例吧。

    但是,如果只能改变列,那么是不会存在后效性的。

    同时注意到,n的大小是10,可以暴力2^n,枚举每一行时候变化,然后贪心变列。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 200 + 20;
    LL a[maxn][maxn];
    LL b[maxn][maxn];
    int n, m, k;
    LL x;
    void init() {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                b[i][j] = a[i][j];
            }
        }
    }
    int calc(int val) { //复杂度O("1"的个数)
        int ans = 0;
        while (val) {
            val &= val - 1;
            ans++;
        }
        return ans;
    }
    void change(int val) {
        for (int i = 0; i <= n - 1; ++i) {
            if ((val & (1 << i)) != 0) {
                for (int j = 1; j <= m; ++j) {
                    b[i + 1][j] = x;
                }
            }
        }
    }
    struct node {
        LL sum;
        int id;
        bool operator < (const struct node & rhs) const {
            if (sum != rhs.sum) return sum < rhs.sum;
            else return id < rhs.id;
        }
    }c[maxn];
    void did(int lef) { //还剩下lef次操作
        int lenc = 0;
        for (int i = 1; i <= m; ++i) {
            LL sum = 0;
            for (int j = 1; j <= n; ++j) {
                sum += b[j][i];
            }
            ++lenc;
            c[lenc].sum = sum;
            c[lenc].id = i;
        }
        sort(c + 1, c + 1 + lenc);
        int en = min(lenc, lef);
        for (int i = 1; i <= en; ++i) {
    //        if (c[i].sum >= x * n) return;
            for (int j = 1; j <= n; ++j) {
                b[j][c[i].id] = x;
            }
        }
    }
    LL now() {
        LL ans = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                ans += b[i][j];
            }
        }
        return ans;
    }
    void work() {
        cin >> n >> m >> x >> k;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                cin >> a[i][j];
            }
        }
        LL ans = 0;
        int en = (1 << n) - 1;
        for (int i = 0; i <= en; ++i) {
            if (calc(i) > k) continue;
            init();
            change(i);
            did(k - calc(i));
            ans = max(ans, now());
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    wa的,还要用了BIT的超级复杂的代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 200 + 20;
    LL row[maxn][maxn], col[maxn][maxn];
    int n, m;
    int lowbit(int x) {
        return x & (-x);
    }
    void upDate(int which, int id, int pos, LL val) {
        if (which == 1) {
            while (pos <= m) {
                row[id][pos] += val;
                pos += lowbit(pos);
            }
        } else {
            while (pos <= n) {
                col[id][pos] += val;
                pos += lowbit(pos);
            }
        }
    }
    LL ask(int which, int id, int pos) {
        LL ans = 0;
        if (which == 1) {
            while (pos) {
                ans += row[id][pos];
                pos -= lowbit(pos);
            }
        } else {
            while (pos) {
                ans += col[id][pos];
                pos -= lowbit(pos);
            }
        }
        return ans;
    }
    void tochange(int which, int id, LL val) {
        if (which == 1) {
            for (int i = 1; i <= m; ++i) {
                LL now = ask(which, id, i) - ask(which, id, i - 1);
                upDate(which, id, i, -now);
                upDate(which, id, i, val);
            }
            for (int i = 1; i <= m; ++i) {
                LL now = ask(2, i, id) - ask(2, i, id - 1);
                upDate(2, i, id, -now);
                upDate(2, i, id, val);
            }
        } else {
            for (int i = 1; i <= n; ++i) {
                LL now = ask(which, id, i) - ask(which, id, i - 1);
                upDate(which, id, i, -now);
                upDate(which, id, i, val);
            }
            for (int i = 1; i <= n; ++i) {
                LL now = ask(1, i, id) - ask(1, i, id - 1);
                upDate(1, i, id, -now);
                upDate(1, i, id, val);
            }
        }
    }
    void work() {
        LL x;
        int k;
        cin >> n >> m >> x >> k;
    //    scanf("%d%d%lld%d", &n, &m, &x, &k);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                int t;
                scanf("%d", &t);
                upDate(1, i, j, t);
                upDate(2, j, i, t);
            }
        }
    //    tochange(1, 1, 10);
    //    cout << ask(2, 2, n) << endl;
        for (int i = 1; i <= k; ++i) {
            LL canadd = 0;
            int id = 0;
            for (int j = 1; j <= n; ++j) {
                LL cango = x * m;
                LL sum = ask(1, j, m);
                if (cango > sum && cango - sum > canadd) {
                    canadd = cango - sum;
                    id = j;
                }
            }
            for (int j = 1; j <= m; ++j) {
                LL cango = x * n;
                LL sum = ask(2, j, n);
                if (cango > sum && cango - sum >= canadd) {
                    canadd = cango - sum;
                    id = j + n;
                }
            }
            if (id == 0) break;
            if (id <= n) {
                tochange(1, id, x);
            } else {
                id -= n;
                tochange(2, id, x);
            }
        }
        LL ans = 0;
        for (int i = 1; i <= n; ++i) {
            ans += ask(1, i, m);
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    头文件板子
    终极快速读入挂极其使用方法
    upc组队赛18 THE WORLD【时间模拟】
    upc 组队赛18 STRENGTH【贪心模拟】
    upc组队赛17 Stone Game【极小值】
    upc组队赛17 Greatest Common Divisor【gcd+最小质因数】
    upc组队赛17 Bits Reverse【暴力枚举】
    upc组队赛16 Winner Winner【位运算】
    20181217RPC
    20181217 分布式与集群
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6432348.html
Copyright © 2020-2023  润新知