Daemon's tech-blog

If you want a miracle, to be the miracle!

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

DIV 1

500ptr BaronsAndCoins

给出n(<=50)个点的坐标,从(0,0)开始,每步(x,y)->(x+ki,y+1),满足ki>ki-1,求最多取多少个点。

DP,令f[i][j]表示当前到达第i个点,已经取了j个点的最小k值。则f[i][j] = min{f[k][j-1]+w(f[k][j-1], k, i)|k<i}。计算w(k, i)时,利用了一种贪心的思想。先假设每步ki的增量都为1,之后多余的x差由每步ki增1调整。直到满足。
#define MaxN 60
#define INF 1000000000
struct Point {
    int x, y;
}c[MaxN];
int f[MaxN][MaxN];
bool cmp(Point a, Point b)
{
    if (a.y != b.y) return a.y < b.y;
    return a.x < b.x;
}
int calc(int s, int y, int x)
{
    int sum = 0;
    for (int i = 1; i <= y; i++)
        sum += s+i;
    if (x < sum) return INF;
    else return s+y+(x-sum)/y+((x-sum)%y!=0);
}
class BaronsAndCoins {
public:
    int getMaximum(vector <int> x, vector <int> y) {
        int n = x.size(), ans = 0;
        for (int i = 0; i < n; i++)
            c[i].x = x[i], c[i].y = y[i];
        sort(c, c+n, cmp);
        for (int i = 0; i < n; i++)
            for (int j = 1; j <= n; j++)
                f[i][j] = INF;
        for (int i = 0; i < n; i++)
            f[i][1] = calc(0, c[i].y, c[i].x);
        for (int k = 2; k <= n; k++)
            for (int i = 0; i < n; i++)
                for (int j = 0; j < i; j++)
                    if (c[j].y < c[i].y && c[j].x < c[i].x)
                        f[i][k] = min(f[i][k], calc(f[j][k-1], c[i].y-c[j].y, c[i].x-c[j].x));
        for (int i = 0; i < n; i++)
            for (int j = 1; j <= n; j++)
                if (f[i][j] < INF && j > ans) ans = j;
        return ans;
    }
}; 

1000ptr  BrickPuzzle

 不会。。。

DIV 2

500ptr BoredPhilosophers

求文本的不同的长度为i(1<=i<=n)的连续单词组成的句子个数。

主要考察istringstream类的用法:istringstream类用于执行C++风格的串流的输入操作

class BoredPhilosophers {
public:
    vector <int> simulate(vector <string> t, int n) {
        string s, tmp;
        vector <string> word;
        vector <int> ret;
        for (int i = 0; i < t.size(); i++)
            s += t[i];
        istringstream sin(s);
        while (sin >> tmp)
            word.push_back(tmp);
        for (int len = 1; len <= n; len++) {
            int cnt = 0;
            map <string, bool> mp;
            for (int i = 0; i+len <= word.size(); i++) {
                string text = "";
                for (int j = i; j < i+len; j++)
                    text += word[j]+' ';
                if (mp.find(text) == mp.end()) {
                    cnt++;
                    mp[text] = 1;
                }
            }
            ret.push_back(cnt);
        }
        return ret;
    }
}; 

1000ptr PizzaDelivery

从餐馆向大楼送Pizza, 'X'表示餐馆,‘#’表示大楼,‘0’-‘9’表示空地高度,相邻高度差为0,时间为1,差为1,时间为3,否则不可达。大楼或餐馆与其它点间时间为2。求两个送餐员送达全部大数的最短时间(最后一次可不回到餐馆)。

先计算出从'$'到所有'#'的最短路,再用位压缩记录集合,枚举一个送餐员的大楼集合。

int n, m, d[MaxN], que[MaxN*20], f[1<<21], w[MaxN];
bool inque[MaxN];
string str;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
void SPFA(int s)
{
    int closed = 0, open = 0, nx, ny, u, v, w;
    memset(inque, 0, sizeof(inque));
    memset(d, 0x3f, sizeof(d));
    que[open++] = s;
    d[s] = 0;
    str[s] = '$';
    do {
        u = que[closed++];
        inque[u] = 0;
        for (int i = 0; i < 4; i++) {
            nx = u/m+dx[i], ny = u%m+dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                v = nx*m+ny;
                if (str[u] == '$' || str[v] == '$') w = 2;
                else if (str[u] == str[v]) w = 1;
                else if (str[u]-str[v] == 1 || str[v]-str[u] == 1) w = 3;
                else continue;
                if (d[u]+w < d[v]) {
                    d[v] = d[u]+w;
                    if (!inque[v]) {
                        inque[v] = 1;
                        que[open++] = v;
                    }
                }
            }
        }
    } while (closed < open);
}
class PizzaDelivery {
public:
    int deliverAll(vector <string> mat) {
        n = mat.size(), m = mat[0].size(); str.clear();
        for (int i = 0; i < n; i++) str += mat[i];
        for (int i = 0; i < n*m; i++)
            if (str[i] == 'X')
                SPFA(i);
        int cnt = 0;
        for (int i = 0; i < n*m; i++)
            if (str[i] == '$') {
                if (d[i] > 5000) return -1;
                w[cnt++] = d[i];
            }
        int U = (1<<cnt)-1, ret = 1000000000, t;
        memset(f, 0, sizeof(f));
        for (int i = 0; i <= U; i++) {
            t = 0;
            for (int j = 0; j < cnt; j++)
                if ((i>>j)&1) {
                    f[i] += 2*w[j];
                    if (w[j] > t)
                        t = w[j];
                }
            f[i] -= t;
        }
        for (int i = 0; i <= U; i++)
            ret = min(max(f[i], f[U-i]), ret);
        return ret;
    }
}; 

posted on 2009-10-28 22:11  ACing  阅读(168)  评论(0)    收藏  举报