圆周率是一个无理数,求出两个数组公共的最长的上升子序列(可以不是连续的子序列)

圆周率是一个无理数, 圆周率即圆的周长与直径的比值,求出两个数组公共的最长的上升子序列(可以不是连续的子序列),最长公共子序列,这个题目也是典型的最小生成树算法,也就是说任何点之间都有路径可以到达,math.h&gt,void main(),//扫雷游戏,包括扫雷游戏

 圆周率即圆的周长与直径的比值。我国南北朝时期的数学家祖冲之把圆周率精确到小数点后
七位,领先并保持世界纪录900年。此外他还发现了一个非常接近圆周率的分数:
355/113=3.1415929 。圆周率是一个无理数,其前22位巧记法如下:
山巅一寺一壶酒 尔乐苦煞吾 把酒吃 酒杀尔 杀不死 乐而乐
3.   1 4 1 5 9  2 6 5 3 5 8 9 7   9 3 2  3 8 4  6 2 6
可以用下列无穷数列求π的近似值:
π/4=1/1-1/3+1/5-1/7+……
(π*π)/6=1/(1*1)+1/(2*2)+1/(3*3)+…… 下面用公式1近似求解π的值:

zoj2432 hdoj1423 最长公共上升子序列(LCIS),zoj2432hdoj1423

zoj2431
 

hdoj
1423 

题意:

一看题目题意就很明显了,
两个数组a,b,求出两个数组公共的最长的上升子序列(可以不是连续的子序列)。

分析:

如果做过[最长公共子序列](

定义状态d[i][j]表示以a数组的前i个元素,b数组的前j个元素并且以b[j]为结尾的LCIS的长度。

首先:a[i] != b[j]时, d[i][j] =
d[i-1][j];  
因为 d[i][j] 是以
b[j] 为结尾的LCIS,如果 d[i][j] >
0 那么就说明 a[1] …. a[i] 中必然有一个元素 a[k]
等于 b[j]。因为 a[k] != a[i],那么 a[i] 对 d[i][j]
没有贡献,于是我们不考虑它照样能得出 d[i][j]
的最优值。所以在 a[i] != b[j] 的情况下必然有 d[i][j] =
d[i-1][j]。这一点参考LCS的处理方法。

当a[i]==b[j]时,
首先,这个等于起码保证了长度为1的LCIS。然后我们还需要去找一个最长的且能让b[j]接在其末尾的LCIS。之前最长的LCIS在哪呢?首先我们要去找的d数组的第一维必然是i-1。因为i已经拿去和b[j]配对去了,不能用了。第二维需要枚举
b[1] … b[j-1]了,因为你不知道这里面哪个最长且哪个小于
b[j]。

状态转移方程:

a[i] != b[j]: d[i][j]=d[i-1][j]

a[i] == b[j]: d[i][j]=max(d[i-1][k]) + 1
; (1<= k <= j-1)

不难看到,这是一个时间复杂度为O(n^3)的DP,离平方还有一段距离。

但是,这个算法最关键的是,如果按照一个合理的递推顺序,max(d[i-1][k])的值我们可以在之前访问 d[i][k]
的时候通过维护更新一个max变量得到。怎么得到呢?首先递推的顺序必须是状态的第一维在外层循环,第二维在内层循环。也就是算好了
d[1][n2]
再去算 d[2][1]。
如果按照这个递推顺序我们可以在每次外层循环的开始加上令一个max变量为0,然后开始内层循环。当a[i]>b[j]的时候令max = d[i-1][j]。如果循环到了a[i] == b[j]的时候,则令 d[i][j] =
max+1。 最后答案是 d[n1][1] …
d[n1][n2]的最大值。

举个例子

a={1, 4, 2, 5, -12}   b ={5, -12, 1, 2, 4, 5}

 

        5      -12     1     2     4     5  
  1     0    0   1   0   0   0
  4      0    0   1   0   2   0
  2   0    0   1   2   2   0
  5   1    0   1   2   2   3
  -12   1    1   1   2   2   3

              if(a[i] == b[j])

                  d[i][j] = mx + 1;

              else  if(a[i] > b[j] && mx < d[i-1][j]) 

*                  mx = d[i-1][j];*

*       *//只有当a[i] > b[j]时,才更新mx,
保证了所求序列是上升的。

 

仔细看表格会发现: 若d[i][j] > 0
的话,那么在数组a前i个元素中一定存在a[k]( 1 <= k <=
i)等于b[j]. 否则说明前i个a元素中没有与b[j]相同的元素。

zoj2432

图片 1#include<iostream>
#include<cstdio> #include<string.h>
#include<cstring> #include<math.h> using namespace std;
const int N = 505; int n1, n2, t, mx, sum; int a[N], b[N],
d[N][N], pi[N][N], pj[N][N]; void dp() { for(int i = 1; i
<= n1; i++) { int mx = 0, x = 0, y = 0; for(int j = 1; j <= n2;
j++) { d[i][j] = d[i-1][j]; pi[i][j] = i-1; pj[i][j] =
j; if(a[i] > b[j] && mx < d[i-1][j]) { mx = d[i-1][j];
x = i-1; y = j; } else if(a[i] == b[j]) { d[i][j] = mx + 1;
pi[i][j] = x; pj[i][j] = y; } } } } void ac(int x, int y) {
if(d[x][y] == 0) return; int fx = pi[x][y]; int fy =
pj[x][y]; ac(fx, fy); if(d[x][y] != d[fx][fy] && y != 0) {
printf(“%d”, b[y]); sum++; if(sum < mx) printf(” “); else
printf(“\n”); } } int main() { cin >> t; while(t–) { scanf(“%d”,
&n1); for(int i = 1; i <= n1; i++) scanf(“%d”, &a[i]); scanf(“%d”,
&n2); for(int i = 1; i <= n2; i++) scanf(“%d”, &b[i]); memset(d, 0,
sizeof(d)); memset(pi, -1, sizeof(pi)); memset(pj, -1, sizeof(pj));
dp(); mx = 0; int flag = 0; for(int i = 1; i <= n2; i++) {
if(d[n1][i] > mx) { mx = d[n1][i]; flag = i; } }
printf(“%d\n”, mx); for(int i = 1; i <= n1; i++) { for(int j = 1; j
<= n2; j++) printf(“%d “, d[i][j]); printf(“\n”); } sum = 0;
if(mx > 0) ac(n1, flag); if(t) printf(“\n”); } return 0; } View Code

 

hdoj1423

图片 2#include<iostream>
#include<cstdio> #include<string.h>
#include<cstring> #include<math.h> using namespace std;
int n1, n2, t, k; int a[505], b[505], d[505][505]; int dp() {
int mx; for(int i = 1; i <= n1; i++) { mx = 0; for(int j = 1; j <=
n2; j++) { d[i][j] = d[i-1][j]; if(a[i] > b[j] && mx <
d[i-1][j]) mx = d[i-1][j]; else if(a[i] == b[j]) d[i][j]
= mx + 1; } } mx = 0; for(int i = 1; i <= n2; i++) { if(d[n1][i]
> mx) mx = d[n1][i]; } return mx; } int main() { cin >> t;
while(t–) { scanf(“%d”, &n1); for(int i = 1; i <= n1; i++)
scanf(“%d”, &a[i]); scanf(“%d”, &n2); for(int i = 1; i <= n2; i++)
scanf(“%d”, &b[i]); memset(d, 0, sizeof(d)); int ans = dp();
printf(“%d\n”, ans); if(t) printf(“\n”); } return 0; } View Code

 

 

 

hdoj1423
最长公共上升子序列(LCIS),zoj2432hdoj1423 zoj2431
hdoj
1423…

这个题目也是典型的最小生成树算法,跟之前的那个题目是差不多的,也就是说:给你n个二维平面点,
让你添加适当的边,使得所有的点都在同一个联通分支上,也就是说任何点之间都有路径可以到达。
问题规模不大,直接用矩阵存数据,利用prim
算法就可以搞定。此时任意两点之间的“权值”就是
两点之间的距离。  1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<math.h>
 4 #include<string.h>
 5 const double MAX = 1000000000.0;
 6 struct Point
 7 {
 8        double x, y;
 9 }point[101];
10
11 double map[101][101];
12 int v[101], n;
13
14 double Dis(Point a, Point b)
15 {
16        return sqrt((a.x – b.x) * (a.x – b.x) +(a.y – b.y) * (a.y –
b.y));
17 }
18
19 void Build()
20 {
21      memset(map, 0, sizeof(map));
22      for (int i=0; i<n; i++)
23      {
24          for (int j=i; j<n; j++)
25          {
26              if (i == j) map[i][j] = MAX;
27              else
28              {
29                    map[j][i] = map[i][j] = Dis(point[i],
point[j]);
30              }
31          }
32      }
33 }
34
35 void MinTree()
36 {
37      double sum = 0.0, min;
38      memset(v, 0, sizeof(v));
39      v[0] = 1;
40      int flag;
41      for (int i=1; i<n; i++)
42      {
43          min = MAX;
44          for (int j=0; j<n; j++)
45          {
46              if (!v[j] && map[0][j] < min)
47              {
48                 min = map[0][j];
49                 flag = j;
50              }
51          }
52          sum += min;
53          v[flag] = 1;
54          for (int j=0; j<n; j++)
55          {
56              if (!v[j] && map[0][j] > map[flag][j])
57              {
58                 map[0][j] = map[flag][j];
59              }
60          }
61      }
62      printf(“%.2lf\n”,sum);
63 }
64 int main()
65 {
66     while (scanf(“%d”, &n)!= EOF)
67     {
68           map[n][n];
69           point[n];
70           for (int i=0; i<n; i++)
71           {
72               scanf(“%lf %lf”, &point[i].x, &point[i].y);
73           }
74           Build();
75           MinTree();
76     }
77     return 0;
78 }
79

C语言实现源码,供参考!

 在此提供C语言小游戏源码,包括扫雷游戏,贪吃蛇游戏,时钟等。

#include<stdio.h>
#include<math.h>
void main()
{
    double pi=0, x;
    int i=-1,flag=-1;
    do{
        i+=2;
        flag*=-1;
        x=flag/(1.0*i);
        pi+=x;
    }while(fabs(x)>1e-6);
        pi*=4;
    printf(“%g\n%d\n”,pi,i);
}

让你添加适当的边,使得所有的点…

余弦函数:

运行时只要把红色部分改为自己电脑上TC目录的BGI分目录即可。