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;
}
};

浙公网安备 33010602011771号