Daemon's tech-blog

If you want a miracle, to be the miracle!

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

DIV 1

500ptr StrongEconomy

你有n个工厂和k个专家,增加一个工厂或专家需要花费price,每时刻会增加n*k,求达到target的最短时间。

思路:

1)晚买不如果早买。

2)让nk尽量接近。

分析可知,我们不应按时间模拟,而应按购买过程模拟。由target <= 10^12。可知在2*10^6内可出解。

注意初始情况下,有可能n*k越界,加个特判。

class StrongEconomy {
public:
    long long earn(long long n, long long m, long long p, long long t) {
        if (t/n < m) return 1;
        long long time = 0, cur = 0, s = n*m, ret = (t+s-1)/s, d;
        while (s <= t) {
            ret = min(ret, time+(t-cur+s-1)/s);
            if (cur < p) {
                d = (p-cur+s-1)/s;
                time += d;
                cur += d*s;
            }
            cur -= p;
            n < m ? n++ : m++;
            s = n*m;
        }
        return min(ret, time+1);
    }
};

1000ptr RowGame

不会。。。

DIV 2

500ptr OrderedNim

在nim博弈的基础上,只有前面各堆均取完时,才能取此堆。

思路:实际上是限制了nim必须从左向右进行。

1)从右向左推(由终点向起点推),如果该堆为1,别无选择,win = !win;如果该堆>1,win = 1。

 class OrderedNim {
public:
    string winner(vector <int> a) {
        bool win = 0;
        for (int i = a.size()-1; i >= 0; i--)
            if (a[i] > 1) win = 1;
            else win = !win;
        return win ? "Alice" : "Bob";
    }
};

2)从左向右推(由起点向终点推),如果该堆为1,别无选择,win = !win;如果该堆>1,胜负已定,跳出。

class OrderedNim {
public:
    string winner(vector <int> a) {
        bool win = 0;
        for (int i = 0; i < a.size(); i++) {
            win = !win;
            if (a[i] > 1)
                break;
        }
        return win ? "Alice" : "Bob";
    }
};

1000ptr EnemyTowers

myUnits个生命值为1的士兵,分成两份去攻击生命值为hpT,攻击力为attackTnumWodT个木塔和numStoT个石塔。每轮由我方先攻击,求最少多少轮消灭敌人,无解返回-1。

思路:

1)人员分配可二分。

2)time(myUnits, hpT, attackT, numT)计算用myUnits个士兵打numT个塔所需时间。

 显然,我们应当采取逐个消灭的策略。因此,记录塔的总生命值为total,则当前剩余的塔数为ceil(total/hp)。模拟即可。

 #define INF 1000000000
int time(int n, int hp, int k, int t)
{
    int total = hp*t, ret = 0;
    while (n > 0 && total > 0) {
        ret++;
        total -= n;
        n -= (total+hp-1)/hp*k;
    }
    if (total <= 0) return ret;
    return INF;
}
class EnemyTowers {
public:
    int attack(int n, int hp, int k, int wd, int st) {
        int l = 0, r = n;
        while (r-l > 1) {
            int mid = (l+r)>>1;
            if (time(mid, hp, k, wd) < time(n-mid, hp, k, st))
                r = mid;
            else
                l = mid;
        }
        int ret = min(max(time(l, hp, k, wd), time(n-l, hp, k, st)), max(time(r, hp, k, wd), time(n-r, hp, k, st)));
        return ret == INF ? -1 : ret;
    }
};

posted on 2009-10-30 09:54  ACing  阅读(190)  评论(0)    收藏  举报