作者归档:admin

积木城堡 

【问题描述】XC的儿子小XC最喜欢玩的游戏用积木垒漂亮的城堡。城堡是用一些立方体的积木垒成的,城堡的每一层是一块积木。小XC是一个比他爸爸XC还聪明的孩子,他发现垒城堡的时候,如果下面的积木比上面的积木大,那么城堡便不容易倒。所以他在垒城堡的时候总是遵循这样的规则。

小XC想把自己垒的城堡送给幼儿园里漂亮的女孩子们,这样可以增加他的好感度。为了公平起见,他决定把送给每个女孩子一样高的城堡,这样可以避免女孩子们为了获得更漂亮的城堡而引起争执。可是他发现自己在垒城堡的时候并没有预先考虑到这一点。所以他现在要改造城堡。由于他没有多余的积木了,他灵机一动,想出了一个巧妙的改造方案。他决定从每一个城堡中挪去一些积木,使得最终每座城堡都一样高。为了使他的城堡更雄伟,他觉得应该使最后的城堡都尽可能的高。

任务:

请你帮助小XC编一个程序,根据他垒的所有城堡的信息,决定应该移去哪些积木才能获得最佳的效果。

【输入格式 Input Format】
第一行是一个整数N(N<=100),表示一共有几座城堡。以下N行每行是一系列非负整数,用一个空格分隔,按从下往上的顺序依次给出一座城堡中所有积木的棱长。用-1结束。一座城堡中的积木不超过100块,每块积木的棱长不超过100。

【输出格式 Output Format】
一个整数,表示最后城堡的最大可能的高度。如果找不到合适的方案,则输出0。

【样例输入 Sample Input】
2
2 1 –1
3 2 1 –1

【样例输出 Sample Output】
3

【算法分析】
多次装箱

【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdio.h>
#include <stdlib.h>
 
int a[101][10001], b[101];
int main()
{
       int n, i, j, k, max, min, m, flag, pp;
 
       scanf("%d", &n);
       memset(a, 0, sizeof(a));
 
       min = 100001;
       for (k = 1; k <= n; k++)
       {
              b[0] = 0;
              scanf("%d", &m);
              while (m != -1)
              {
                     b[++b[0]] = m;
                     scanf("%d", &m);
              }
 
              a[k][0] = 1;
              max = 0;
 
              for (i = 1; i <= b[0]; i++)
              {
                     for (j = max; j >= 0; j--)
                     {
                            if (a[k][j] == 1 && j + b[i] <= min)
                            {
                                   a[k][j + b[i]] = 1;
                                   if (j + b[i] > max)
                                          max = j + b[i];
                            }
                     }
              }
 
              if (max > min)
                     min = max;
 
       }
 
       flag = -1;
       for (i = min; i > 0; i--)
       {
              for (k = 1; k <= n; k++)
                     if (a[k][i] == 0)
                            break;
 
                     if (k > n)
                     {
                            flag = k;
                            max = i;
                            break;
                     }
       }
 
       if (flag == -1)
              printf("0\n");
       else
              printf("%d\n", max);
 
       return 0;
}

使用VC6.0生成VLD扩展

使用VC6.0生成VLD扩展

最近想看看PHP生成的源码是啥样子,于是google半天,终于完成。
环境:VC6.0
源码:php5.2.9源码包(可以去http://www.php.net/下载),解压,我的是解压在D盘根目录下。
Vld源码包(可以去http://pecl.php.net/package/vld/0.9.1下载),解压

生成过程如下:
1、在Windows平台启动 VC++ 6.0, 【文件】(File)->【新建】(New), 在 【工程】(Project)中选择 【Win32 Dynamic-Link Library】, 填写上 【工程名称】(Project Name) 和 【位置】(Location),如图1所示:

图1

图1

2、点击确定后,在第二屏选中 【一个空的DLL工程】(An empty DLL project), 点 【完成】Finish, 完成创建。此时会可能会弹出一个信息框,点击确定。

3、把解压后的vld源码中的vld文件夹下面的所有文件拷贝到到工程所在的目录(D:\php-5.2.9\ext\vld);

4、选择左侧的【Source Files】,点击右键,选择【添加文件到目录】,将D:\php-5.2.9\ext\vld目录下的所有C文件添加到此目录,如图2所示;

图2

图2

5、同样选择【Header Files】,添加所有的头文件到目录。如图3所示:

图3

图3

6、修改工程设置,选择【工程】(Project)->【设置】(Settings)->【C/C++】,在【工程选项】(Project Options:)的 最后加上 /Tc,在预处理程序定义中添加如下宏定义:ZEND_DEBUG=0,COMPILE_DL_VLD,ZTS=1,ZEND_WIN32,PHP_WIN32,HAVE_VLD=1

如果你需要编译其它扩展,请将COMPILE_DL_VLD 和 HAVE_VLD=1,后面的 “VLD” 改成和你要创建的工程名一致。

如图4所示:

 

图4

图4

7、选择【连接】(Link),在【对象/库模块】(Object/library modules)添加php5ts.lib,注意要以空格格开;

8、选择【工具】(Tools)->【选项】(Options)->【目录】(Directories),

在 【目录】(Show directories for:) 下拉框中选择 “Library files”,在 【路径】(Directories) 中添加 D:\php-5.2.9 (即 php5ts.lib 所在目录);如图5所示:

在【目录】(Show directories for:) 下拉框中选择 “Include files”

在【路径】(Directories)中添加 D:\PHP-5.2.9 (即 ext、regex、win32 所在目录)

在【路径】(Directories)中添加 D:\PHP-5.2.9\MAIN

在【路径】(Directories)中添加D:\PHP-5.2.9\ZEND

在【路径】(Directories)中添加 D:\PHP-5.2.9\TSRM

如图6所示: 

 

图5

图5

 

 

图6

图6

9、选择【组建】->【编译】,此时可能会出现报错。

php_vld.h文件的59行存在三个莫名其妙的点,将他们去掉就可以了。

10、选择【组建】->【组建】。成功!

在扩展下的Debug目录D:\php-5.2.9\ext\vld\Debug下有一个生成的dll文件。这就是我们所要的东东了!

 

搭建双塔 

问题描述
  2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难。为了纪念“9-11”事件,Mr. F决定自己用水晶来搭建一座双塔。

  Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建。但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少。所以他来请你帮忙。

  给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建的双塔的最大高度,否则输出“Impossible”。

输入格式 Input Format
  输入的第一行为一个数N,表示水晶的数量。第二行为N个数,第i个数表示第i个水晶的高度。

输出格式 Output Format
  输出仅包含一行,如果能搭成一座双塔,则输出双塔的最大高度,否则输出一个字符串“Impossible”。

样例输入 Sample Input
5
1 3 4 5 2

样例输出 Sample Output
7

算法分析
f[i,j]表示前i个分成差为j的两堆时的最大高度
f[i,j]=max{f[i-1,j],
     f[i-1,j+v[i]],
     f[i-1,j-v[i]]+v[i],(j-v[i]>=0)
     f[i-1,abs(j-v[i])]-abs(j-v[i])+v[i],(j-v[i]<0)} 答案就是f[n,0] 如果f[n,0]=0就impossible 【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#define max(a,b) (a>b ? a:b)
 
int main()
{
       int n, m = 0, i, j;
       int h[101];
       int dp[101][2001] = {0}; 
 
       scanf("%d",&n);
       for(i = 1; i <= n; i++)
       {
              scanf("%d", &h[i]);
              m += h[i];
       }
       for (i = 1; i <= n; i++)
              for (j = 0; j <= m; j++)
              {
                     dp[i][j] = dp[i-1][j];
                     if(j == h[i])
                            dp[i][j] = max(dp[i][j], dp[i - 1][j - h[i]] + h[i]);
 
                     if(j < h[i] && dp[i - 1][h[i] - j] -h[i] + j >= 0)
                            dp[i][j] = max(dp[i][j], dp[i - 1][h[i] - j] + j);
 
                     if(j > h[i] && dp[i - 1][j - h[i]] + h[i] - j >= 0)
                            dp[i][j] = max(dp[i][j], dp[i - 1][j - h[i]] + h[i]);
 
                     if(j + h[i] <= m)
                            dp[i][j] = max(dp[i][j], dp[i - 1][j + h[i]]);
              }
 
              if(dp[n][0])
                     printf("%d", dp[n][0]);
              else
                     printf("Impossible");   
 
              return 0;
}