SPOJ 14 - I-Keyboard[IKEYB]
动态规划。我们先预处理出必要的区间段信息,然后发现其满足单调性,于是采用单调性优化。我们使用的是f(x)=min{f(i)+w(i,x)}这一经典模型,二分求出决策就可以了,总的复杂度是
。
#include <cstdio>
#include <climits>
#include <cstring>
#include <stack>
using namespace std;
const int MAXN = 90+5;
struct status {
int u,b,e;
status(int _u,int _b,int _e)
: u(_u),b(_b),e(_e) {}
status() {}
};
char ma[MAXN],mb[MAXN];
int n,m,f[MAXN][MAXN],w[MAXN];
int p[MAXN][MAXN],r[MAXN],g[MAXN][MAXN];
stack<status> st[MAXN];
int tdec[MAXN];
int main() {
int ncase;
scanf("%d",&ncase);
for (int loop = 1; loop<=ncase; loop++) {
scanf("%d%d",&m,&n);
scanf("%s%s",ma,mb);
for (int i = 1; i<=n; i++)
scanf("%d",&w[i]);
for (int i = 1; i<=n; i++) {
g[i][i] = w[i];
for (int j = i+1; j<=n; j++)
g[i][j] = g[i][j-1]+w[j]*(j-i+1);
}
f[0][0] = 0;
st[1].push(status(1,1,n));
for (int i = 1; i<=m; i++) {
while (!st[i].empty()) {
status tmp = st[i].top();
for (int j = tmp.b; j<=tmp.e; j++)
p[i][j] = tmp.u;
st[i].pop();
}
for (int j = i; j<=n; j++)
f[i][j] = f[i-1][p[i][j]-1]+g[p[i][j]][j];
if (i<m) {
st[i+1].push(status(i+1,i+1,n));
for (int j = i+2; j<=n; j++) {
while (!st[i+1].empty()) {
int u = st[i+1].top().u;
int b = st[i+1].top().b;
if (j<=b && f[i][u-1]+g[u][b]>f[i][j-1]+g[j][b])
st[i+1].pop();
else break;
}
int u = st[i+1].top().u;
int e = st[i+1].top().e;
if (j<=e && f[i][u-1]+g[u][e]>f[i][j-1]+g[j][e]) {
int l = st[i+1].top().b,r = e; // (]
while (l+1<r) {
int mid = (l+r)/2;
if (j<=mid && f[i][u-1]+g[u][mid]>f[i][j-1]+g[j][mid]) r = mid;
else l = mid;
}
st[i+1].top().e = l;
st[i+1].push(status(j,l+1,n));
}
else if (e+1<=n) st[i+1].push(status(j,e+1,n));
}
}
}
for (int i = m,j = n; i>0; i--) {
r[i] = p[i][j];
j = r[i]-1;
}
r[m+1] = n+1;
printf("Keypad #%d:\n",loop);
for (int i = 1; i<=m; i++) {
printf("%c: ",ma[i-1]);
for (int j = r[i]; j<r[i+1]; j++)
printf("%c",mb[j-1]);
printf("\n");
}
printf("\n");
}
return 0;
}
Your program in C++ from 2010-03-19 08:54:48 ran for 0.53 seconds and used 2792 KB of memory.
本作品遵循“署名-非商业性使用-相同方式共享 3.0 Unported”协议,转载请注明来自richard-desktop。
评论 (0)