UVa10285 Cake Slicing

zh

链接:Link 耗时:1.825s

这道题做的可真够久的:前前后后加起来将近有两个小时,因此当 AC 的那一刻,自己心中还是挺自豪的。

事实上,这是一道复杂一点的区间型动态规划,之所以说“复杂”,是因为它的状态转移是二维的:切蛋糕既可以横切,也可以纵切。由此我想到了分治算法:

假设一个矩形它所需要切的刀数是 f,则 f 可以由组成该矩形的小矩形的 f 值决定。

因此,这个问题具有最优子结构。由于每个状态为一个矩形,因此需要 4 个维度来记录状态(及左上、右下两个顶点)。下面是横切时的状态转移方程,纵切时同理可得:

$$ \begin{aligned} f(up, down, left, right) = &\ min\{f(up, i, left, right) \\ & + f(i, down, left, right) + right - left\},i = up + 1 .. down -1 \end{aligned} $$

{$R-}
const INF = maxint div 5; //正无穷
var
f: array [0..20, 0..20, 0..20, 0..20] of integer;
cherries: array [1..500, 1..2] of integer;
map: array [0..20, 0..20] of boolean;
n, m, i, k: integer;

function min(x, y: integer): integer; inline;
begin
if x<y then exit(x) else exit(y);
end;

function cherryin(u, d, l, r: integer): integer; inline; //判断矩形内有没有樱桃
var
i, j: integer;
begin
cherryin := 0;
for i := u+1 to d do
for j := l+1 to r do
if map[i, j] then
begin
inc(cherryin);
if cherryin = 2 then exit;
end;
end;

function dp(u, d, l, r: integer): integer;
var
b: integer;
i: integer;
begin
if f[u, d, l, r] <> -1 then
exit(f[u,d , l, r]);
b := cherryin(u, d, l, r);
if b = 1 then
begin
f[u, d, l, r] := 0;
exit(0);
end;
if b = 0 then
begin
f[u, d, l, r] := INF;
exit(INF);
end;
dp := INF;
for i := u+1 to d-1 do
dp := min(dp, dp(u, i, l, r)+dp(i, d, l, r)+r-l);
for i := l+1 to r-1 do
dp := min(dp, dp(u, d, l, i)+dp(u, d, i, r)+d-u);
f[u, d, l, r] := dp;
end;

var
_: integer;

begin
assign(input, 'main.in');reset(input);
assign(output, 'main.out');rewrite(output);
_ := 0;
readln(n, m, k);
while n>0 do
begin
inc(_);
fillchar(map, sizeof(map), 0);
fillchar(f, sizeof(f), -1);
for i := 1 to k do
begin
readln(cherries[i, 1], cherries[i, 2]);
map[cherries[i, 1], cherries[i, 2]] := true;
end;
writeln('Case ',_,': ', dp(0,n,0,m));
readln(n, m, k);
end;
close(input);close(output);
end.
READ MORE

UVa10285 Longest Run on a Snowboard

zh

链接:Link 耗时:0.028s

一道简单的动态规划,主要思路就是:用 $f[i,j]$ 表示到达 $(i,j)$ 的最长路径的长度。找到每个最高点,从其开始向四周的低处搜索。如果该点已搜过并且 f 值大于当前长度则退出回溯。直到达到某个最低点为止。

不多说了,直接上代码:

const
delta :array [1..4, 1..2] of integer = ((-1, 0), (1, 0), (0, 1), (0, -1)); //四个方向向量
var
_: Integer;
name: string;
n, m, i, j, x: Integer;
ans: longint;
map: array [0..101, 0..101] of integer;
f: array [1..100, 1..100] of longint;

function max(x, y: longint): longint; inline;
begin
if x>y then exit(x) else exit(y);
end;

function can(x, y: integer): Boolean; inline; //判断是否是最高点
var
i: Integer;
tx, ty: integer;
begin
can := true;
for i := 1 to 4 do
begin
tx := x + delta[i, 1];
ty := y + delta[i, 2];
can := can and (map[x, y] >= map[tx, ty]);
if not can then break;
end;
end;

procedure dp(x, y: integer; len: longint); //回溯进行动态规划
var
i: Integer;
tx, ty: integer;
begin
inc(len);
if f[x, y] > len then exit;
f[x, y] := len;
ans := max(ans, len);
for i := 1 to 4 do
begin
tx := delta[i, 1] + x;
ty := delta[i, 2] + y;
if (tx = 0) or (tx > n) or (ty = 0) or (ty > m) then continue;
if map[x, y] <= map[tx, ty] then continue;
dp(tx, ty, len);
end;
end;

procedure ReadAndProcessName; //处理那行该死的名字!!
var
s: string;
i: integer;
begin
readln(s);
i := 1;
name := '';
n := 0;
m := 0;
while s[i] <> ' ' do
begin
name := name + s[i];
inc(i);
end;
inc(i);
while s[i] <> ' ' do
begin
n := n * 10 + ord(s[i]) - ord('0');
inc(i);
end;
inc(i);
while i <= length(s) do
begin
m := m * 10 + ord(s[i]) - ord('0');
inc(i);
end;
end;

begin
assign(input, 'main.in');reset(input);
assign(output, 'main.out');rewrite(output);
readln(_);
while _>0 do
begin
dec(_);
fillchar(map, sizeof(map), 0);
ReadAndProcessName;

for i := 1 to n do
for j := 1 to m do
begin
read(x);
map[i, j] := x+1;
end;
readln;

fillchar(f, sizeof(f), 0);
ans := 0;
for i := 1 to n do
for j := 1 to m do
if can(i, j) then
dp(i, j, 0);
writeln(name, ': ', ans);
end;
close(input);close(output);
end.
READ MORE

关于 Ubuntu 突然无法连接 Wifi 的解决方案

zh

事实上我也不知道发生了什么,大概是几天前插了“小度 Wifi”的缘故。没有任何征兆地,Wifi 就用不了了。其实我也不知道原理,大概是某个驱动被刷掉了。下面是从网上找来的答案:

sudo apt-get install wicd-daemon

做个记录。

READ MORE

UVa12186 Another Crisis && [Dynamic Arrays in Pascal]

zh

链接:Link 耗时:0.586s

昨晚做的太急了,没时间写总结,正好下午有空,补上。

这是一道典型的树形动态规划,不是很难,但十分坑语言。思路大致如下:

对于第 $i$ 个节点,用 $d(i)$ 表示其上诉所需的最小工人数。若 $i$ 为叶节点,则 $d(i)=1$;否则,遍历求出 $i$ 的子节点所对应的 $d$ 值,并由小到大排序,取出最小的几个相加,即为 $d(i)$。

很容易想到用递归来实现。但对于“子节点的 d 值的排序”实现起来却十分困难:因为事先不知道有多少个数。当然啦,如果是 C++ 组,用 vector 可以轻松搞定,可至于 P 党,实现起来却难上加难。思来想去,决定试试 Pascal 的动态数组。磕磕碰碰调了近 1 个小时,终于 AC 了。

//Accepted
var
tree: array [0..100000] of array of int64;
T: Integer;
f: array [0..100000] of int64;
i,l,n,x:longint;

function min(x,y: int64): int64;
begin
if x<y then exit(x) else exit(y);
end;

procedure sort(var arr: array of int64;l,r:longint); overload;
var
i,j:longint;
m,t: int64;
begin
i := l;
j := r;
m := arr[(l+r) >> 1];
repeat
while arr[i]<m do inc(i);
while arr[j]>m do dec(j);
if i<=j then
begin
t := arr[i];
arr[i] := arr[j];
arr[j] := t;
inc(i);
dec(j);
end;
until i>j;
if i<r then sort(arr, i, r);
if l<j then sort(arr, l, j);
end;

procedure sort(var arr: array of int64); overload;
begin
sort(arr, low(arr), high(arr));
end;
function dp(x: longint): int64;
var
arr: array of int64;
l,i, num: longint;
begin
if f[x] <> 0 then
begin
dp := f[x];
exit;
end;
if length(tree[x]) = 0 then
begin
dp := 1;
f[x] := 1;
exit;
end;
l := length(tree[x]);
SetLength(arr, l);
for i := Low(tree[x]) to High(Tree[x]) do
arr[i] := dp(tree[x][i]);
Sort(arr);
num := (l*T-1) div 100+1;
for i := Low(arr) to num-1 do
f[x] := f[x] + arr[i];
dp := f[x];
end;

begin
assign(input, 'main.in');reset(input);
assign(output,'main.out');rewrite(output);
readln(n, T);
while n>0 do
begin
fillchar(f, sizeof(f), 0);
fillchar(tree, sizeof(tree), 0);
for i := 1 to n do
begin
read(x);
SetLength(tree[x], length(tree[x])+1);
tree[x][high(tree[x])] := i;
end;
readln;
dp(0);
writeln(f[0]);
readln(n, T);
end;
close(input); close(output);
end.

Dynamic Arrays

这里,再总结一下动态数组的用法。

  1. 定义:a: array of [type];
  2. 设置长度: SetLength(a, 10);
  3. 长度加一: SetLength(a, Length(a)+1);
  4. 取得最大、最小下标: High(a), Low(a)

事实上,从 1.1 版本开始 FPC 就支持 Dynamic Arrays 了。所以在 NOIP 竞赛中我们大可放心使用。

READ MORE

UVa11584 Partitioning by Palindromes

zh

这是一道区间型 DP,转移方程很简单,但在实现的过程中却遇见了很多坑,在此记录一下。链接:Link 耗时:0.368s

容易想到,前 $i$ 个数的划分情况可以由 $1,2,3,\ldots,i-1$ 的划分情况来决定。因此很容易得到状态转移方程:

$$d[i] = min(d[i], d[j]+1)$$

其中 $j = 0, 1, 2,\ldots,n-1$ 并且 $s[j+1, i]$ 为回文串,初始条件:$d[i] = i$。$d[i]$ 表示前 i 项的最小划分。这样一来状态转移的复杂度就为 $O(n^2)$。

但状态转移的判断呢?“回文串”是一个复杂的条件,判断一个串是否为回文串需要将该串至少遍历一遍。这样一来时间复杂度就上升为 $O(n^3)$ 了。而事实上在这种算法中有许多无谓的计算,因此我们可以先对字符串进行预处理:用 huiwen[i,j] 表示 $s[i,j]$ 是否为回文串(奇怪的名字。。。)。如此一来,时间复杂度就降为 $O(n^2)$ 了。

var
s: AnsiString;
n, _, i, j, l: integer;
huiwen: array [1..1000, 1..1000] of boolean; //s[i,j]是否为回文串
dp: array [0..1000] of integer; //一定从0开始,否则当整串为回文串时就考虑不到了。

function min(x,y: integer): integer;
begin
if x<y then exit(x) else exit(y);
end;

procedure process(i,j: integer); //对回文串进行预处理
var
mid: Integer;
x,y: integer;
begin
if j = i then
begin
huiwen[i,j] := true;
exit;
end;
mid := i + (j-i+1) shr 1;
x := i;
y := j;
while (x <= mid) and (s[x] = s[y]) do
begin
inc(x);
dec(y);
end;
huiwen[i, j] := x > mid;
end;

begin
//assign(input, 'main.in'); reset(input);
//assign(output, 'main.out'); rewrite(output);
readln(n);
for _ := 1 to n do
begin
readln(s);
l := length(s);
//Pre-process
fillchar(huiwen, sizeof(huiwen), 0);
for i := 1 to l do
for j := i to l do //一定是从i开始,这个错卡了我很久。
process(i, j);
//DP
for i := 1 to l do
begin
dp[i] := i;
for j := 0 to i-1 do
if huiwen[j+1, i] then
dp[i] := min(dp[i], dp[j]+1);
end;
write(dp[l]);
{if _ <>n then }writeln; //吐槽一下:一开始我还谨慎地加上这句以避免行末回车,没想到UVa居然报错了。。看来UVa的比较算法还有待改进啊。
end;

//close(input);close(output);
end.
READ MORE

UVa437 The Tower of Babylon

zh

链接:The Tower of Babylon 耗时:0.015s

这是刘汝佳的紫书中”DAG 中的动态规划”中的习题,我拿它用来熟悉 DAG 中的动态规划。

我们不妨进行逆向考虑:现堆上面的方块,然后考虑在下面进行叠加。这样子一来,影响决策的就只是最下面方块的尺寸了。

对于这种出现了”大套小”这样的二元关系的题,我们可以将其视为一个有向无环图:其中每个节点为一个状态,状态的转移是有固定的方向的(在此题中,状态转移为从小的方块到大的方块)。

但是这道题又不同于平常的 DAG 动态规划:若将边长视为状态的话,则要开一个巨大的数组,这是不可以接受的。因此,我们要换一种思维方式:只记录方块的序号和摆放的方式(如现将边长从小到大进行排序,然后用一个标志 k 表示当前是以第 k 小的边长作为高)。

至此,思路已经清晰了。用 $dp(i, k)$ 表示 “第 i 个方块以第 k 条边为高进行摆放” ,以下给出状态转移方程:

$$dp(i, k) = max\{dp(i, k), dp(j, k_2)\}$$

其中 $j,k_2$ 遍历所有顶面矩形比 $dp(i, k)$ 小的状态。

代码实现首次尝试了 Pascal 中的 object 类型,使其更加工整,但不可避免地损耗了一些性能。

type
Cube = object
a: array [1..3] of longint;
procedure init(x,y,z: longint);
function height(k: integer): longint;
function low(k: integer): longint;
function high(k: integer): longint;
end;

function max(x,y: longint): longint;
begin
if x>y then max := x else max := y;
end;

procedure swap(var x,y: longint);
var
t: longint;
begin
t := x;
x := y;
y := t;
end;

function Cube.height(k: integer): longint;
begin
height := self.a[k];
end;

function Cube.high(k: integer): longint;
begin
case k of
1: high := a[3];
2: high := a[3];
3: high := a[2];
end;
end;

function Cube.low(k: integer): longint;
begin
case k of
1: low := a[2];
2,3: low := a[1];
end;
end;

procedure Cube.init(x, y, z: longint);
begin
if x>y then swap(x,y);
if y>z then swap(y,z);
if x>y then swap(x,y);
a[1] := x;
a[2] := y;
a[3] := z;
end;

var
f: array [1..30, 1..3] of longint;
i,j,m,n,x,y,z: longint;
cnt: longint;
cubes: array [1..30] of Cube;

function dp(id, k: integer): longint;
var
l, h, hi: longint;
i, j: integer;
begin
if f[id, k] > 0 then
exit(f[id, k]);
l := cubes[id].low(k);
hi := cubes[id].height(k);
h := cubes[id].high(k);

f[id, k] := hi;

for i := 1 to n do
begin
//if i = id then continue; //此处在一开始时忘记考虑了立方体有无穷多个这一条件。
for j := 1 to 3 do
begin
if not ((cubes[i].low(j) < l) and (cubes[i].high(j) < h)) then
continue;
f[id, k] := max(f[id, k], dp(i, j)+hi);
end;
end;

dp := f[id, k];
end;

begin
assign(input, 'main.in');reset(input);
assign(output, 'main.out');rewrite(output);
read(n);
cnt := 0;
while n > 0 do
begin
inc(cnt);
for i := 1 to n do
begin
read(x,y,z);
cubes[i].init(x,y,z);
end;
fillchar(f, sizeof(f), 0);

m := 0;
for i := 1 to n do
for j := 1 to 3 do
m := max(m, dp(i, j));

writeln('Case ', cnt, ': maximum height = ', m);

read(n);
end;
close(input);close(output);
end.
READ MORE

NOIP2011 表达式计算

zh

记得 11 年的时候,觉得这道题爆难,根本无从下手。三年后再次回顾,终于 AC 了,就当是对表达式求值和动态规划的复习吧。

题目:Link

// Accepted.
#include <iostream>
#define Mod 10007
using namespace std;

typedef struct {
long long v0; //当前值为 0 的个数
long long v1; //当前值为 1 的个数
char ch; //当前字符
} vertex;

vertex f[100000];

void merge_sum(int p) {
int w0 = f[p-1].v0 * f[p].v0;
int w1 = f[p-1].v0*f[p].v1+f[p-1].v1*f[p].v0+f[p-1].v1*f[p].v1;
f[p-1].v0 = w0 % Mod;
f[p-1].v1 = w1 % Mod;
}

inline void merge_product(int p) //处理当前的值和前一个值取'*'的操作
{
int w0=f[p-1].v0*f[p].v0+f[p-1].v0*f[p].v1+f[p-1].v1*f[p].v0;
int w1=f[p-1].v1*f[p].v1;
f[p-1].v0=w0%Mod;
f[p-1].v1=w1%Mod;
}

int main()
{
int n;
cin>>n;
f[0].v0=f[0].v1=1;
while (n--)
{
now++; //新建一个空位读入新符号
cin>>f[now].ch;
f[now].v0=f[now].v1=1; //初始化当前符号的前面的值 (虽然')'除外,但也不影响)
if (f[now].ch=='+')
{
if (f[now-1].ch=='*') //处理'*'
{
now--;
merge_product(now);
f[now]=f[now+1];
}
if (f[now-1].ch=='+') //处理'+'
{
now--;
merge_sum(now);
f[now]=f[now+1];
}
}
if (f[now].ch=='*')
if (f[now-1].ch=='*') //处理'*'
{
now--;
merge_product(now);
f[now]=f[now+1];
}
if (f[now].ch==')') //处理')'(比较麻烦)
{
now--;
if (f[now].ch=='*')
{
merge_product(now);
now--;
}
if (f[now].ch=='+')
{
merge_sum(now);
now--;
}
now--;
f[now].v0=f[now+1].v0;
f[now].v1=f[now+1].v1;
if (f[now].ch=='*')
{
merge_product(now);
now--;
}
}
}
if (f[now].ch=='*') //处理完了以后,可能还有残留的'*'和'+'
{
merge_product(now);
now--;
}
if (f[now].ch=='+')
{
merge_sum(now);
now--;
}
cout<<f[0].v0;
return 0;
}
READ MORE

Extended 和 Double 的奇怪问题

zh

最近在做一个项目,其中有一段判断一个 Extended 浮点数是否为整数的代码。我用如下方式实现:

function IsInt(F: Extended): Boolean;
begin
result := Trunc(F)-F = 0; //整数部分等于自身
end;

测试了许多样例都过了,唯独这个没过:

IsInt(4.000000002*1000000000); //False

调试时发现: Trunc(F) 居然等于 4000000001!开始以为是精度的问题,找了许多资料也没能解决。后来将 Extended 换成了 Double,就通过了。百思不得其解中。

READ MORE

MySQLDump 导出时不加锁

zh

在 SAE 上进行应用开发时,常常需要导入数据库,这时候就需要用 MySQLDump 工具进行本地数据库导出。

首先 MySQLDump 最基本的语法是这样的 mysqldump <database_name>,执行之后可以在控制台上看到 SQL 源码。但我第一次尝试将导出的源码上传至 SAE 时 SAE 却报错,原因是 SAE 的数据库管理不支持 LOCK 和 UNLOCK 语句。曾有一段时间,我是手动一行行删除 LOCK 语句。。30 多张表那叫一个蛋疼。。后来,我翻阅了 mysqlDump 的 help 文档,发现可以添加这么一个参数--ADD-LOCKS=FALSE。几经尝试后发现果然没有 LOCK 语句了。在此记录下整句命令:

mysqldump --add-locks=FALSE -uroot -p <database_name> > example.sql
READ MORE

窥视香港

zh
mybirth:2eOq+nwSVgLzakGbP0cV/A==:HKqEYTM2VifN0OmWDce2bw==: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
**THIS CONTENT IS ENCRYPTED**
 
DECRYPTING...
READ MORE