返回顶部

POJ - 2586 - Y2K Accounting Bug = 枚举

http://poj.org/problem?id=2586

迷惑的英文,什么乱来的,就算是中文也看不懂啊。北大果然nb。

题意:

每个月会给出一个财务报告:赢利或者亏空 如果赢利则赢利s,如果亏空则亏空d
(12个月都一样,只有赢利s或者亏空d两种情况)
每五个月也会给出一个报告(1~5 ,2~6 。。。)一年一共有8次这样的报告,已知这8次都报告亏空
问整年情况:如果亏空则输出Deficit,如果赢利,输出整年可能赢利的最大值

来源:http://poj.org/showmessage?message_id=114669

所以就是枚举12个月的s或d的状态,使得每个大段都亏空的就更新答案。

注意不要演,12-5=7,但上界并不是7,而是8!因为是小于号。

加个剪枝才可以通过,否则就需要贪心了,贪心的话就优先把s月放在两端。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;

ll s, d;
bool check(int u) {
    for(int i = 0; i < 8; ++i) {
        ll sum = 0;
        for(int j = 0; j < 5; ++j) {
            if((u >> (i + j)) & 1) {
                sum += s;
            } else {
                sum -= d;
            }
        }
        if(sum > 0)
            return false;
    }
    return true;
}

ll ans(int u, int &maxans1) {
    ll sum = 0;
    maxans1 = 0;
    for(int i = 0; i < 12; ++i) {
        if((u >> i) & 1) {
            sum += s;
            ++maxans1;
        } else {
            sum -= d;
        }
    }
    return sum;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    while(~scanf("%lld%lld", &s, &d)) {
        ll maxans = -1e18;
        int maxans1 = 0;
        for(int i = 0; i < (1 << 12); ++i) {
            int cur = 0;
            for(int j = 0; j < 12; ++j) {
                if((i >> j) & 1) {
                    cur++;
                }
            }
            if(cur <= maxans1)
                continue;

            if(check(i)) {
                maxans = max(maxans, ans(i, maxans1));
            }
        }
        if(maxans > 0)
            printf("%lld\n", maxans);
        else
            puts("Deficit");
    }
}

假如可以用奇怪的函数说不定会更快。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;

int s, d;
bool check(int u) {
    for(int i = 0; i < 8; ++i) {
        int sum = 0;
        for(int j = 0; j < 5; ++j) {
            if((u >> (i + j)) & 1) {
                sum += s;
            } else {
                sum -= d;
            }
        }
        if(sum > 0)
            return false;
    }
    return true;
}

int ans(int u, int &maxans1) {
    int sum = 0;
    maxans1 = 0;
    for(int i = 0; i < 12; ++i) {
        if((u >> i) & 1) {
            sum += s;
            ++maxans1;
        } else {
            sum -= d;
        }
    }
    return sum;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    while(~scanf("%d%d", &s, &d)) {
        int maxans = -1e9;
        int maxans1 = 0;
        for(int i = (1 << 12) - 1; i >= 0; --i) {
            int cur = 0;
            for(int j = 0; j < 12; ++j) {
                if((i >> j) & 1) {
                    cur++;
                }
            }
            if(cur <= maxans1)
                continue;

            if(check(i)) {
                maxans = max(maxans, ans(i, maxans1));
            }
        }
        if(maxans > 0)
            printf("%d\n", maxans);
        else
            puts("Deficit");
    }
}

最大的一定是

++++++++++++

但它不可能亏损

加入亏损的话,按道理应该尽可能使亏损的覆盖面大,也就是
假如只需要亏损1次:

++++-++++-++

假如亏损2次:

+++--+++--++

假如亏损3次:

++---++---++

假如亏损4次 :

+----+----+-
posted @ 2019-10-21 22:08  Inko  阅读(95)  评论(0编辑  收藏  举报