码迷,mamicode.com
首页 > 编程语言 > 详细

第三章算法作业(求助攻)

时间:2016-04-18 10:12:54      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:

3-1.LIS(longest increas sequence)不多说,题目说了要($ O(n^2) $),我还能说什么呢?

  相同题目:HDU 1087 super jumping !jumping!jumping! 而且不卡平方的做法

  用dp[i]表示以 i 个数结尾的序列的LIS长度,初始化为dp[i] = 1 ($ 1 \leq i \leq n $)下面附一神代码

技术分享
 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 int num[5005],d[5005];
 6 
 7 int main(void)
 8 {
 9     int n; cin>>n;
10     for(int i=0;i<n;i++) scanf("%d",num+i);
11     for(int i=0;i<n;i++)
12     {
13         d[i]=1;
14         for(int j=0;j<i;j++)
15             if(num[j]<=num[i]) d[i]=max(d[i],d[j]+1);
16     }
17     int ans=0;
18     for(int i=0;i<n;i++) ans=max(ans,d[i]);
19     printf("%d\n",ans);
20     return 0;
21 }
Aguin

3-2. 依旧LIS,不过要求 $ O(log(n)) $的算法。

  用 dp[cnt]保存长度为cnt的LIS中最后一个数最小的那个数,刚开始,dp[1]为序列中最小的数,对于 num[i]($ 2 \leq i $),如果num[i] > dp[1] ,则dp[2] = num[i],否则,在dp数组中找到比num[i]大的数中最小的那个数(dp数组是有序的,直接二分就ok)更新dp数组:dp[找到的位置] = num[i],最后cnt就是答案啊!

  相同题目:NYOJ 17 单调递增最长子序列 很棒的一个题目,平方做法不能AC

   

技术分享
 1  
 2 /*************************************************************************
 3     > File Name: lis.cpp
 4     > Author: 
 5     > Mail: 
 6     > Created Time: 2016年03月27日 星期日 20时59分03秒
 7  ************************************************************************/
 8 
 9 #include <iostream>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <cstring>
13 #include <algorithm>
14 #include <cmath>
15 
16 using namespace std;
17 const int maxn = 10010 ;
18 char s[maxn] , d[maxn] ;
19 
20 inline int reads()
21 {
22     int i = 0 ;
23     char c = getchar() ;
24     if (c == \n) c = getchar() ;
25     while (c != \n) {
26         s[++i] = c ;
27         c = getchar() ;
28     }
29     return i ;
30 }
31 
32 int main()
33 {
34  //   freopen("in","r",stdin) ;
35     int T , len ;
36     scanf("%d",&T) ;
37     while (T --) {
38         len = reads() ;
39         d[1] = s[1] ;
40         int cnt = 1 ;
41         for (int i = 2 ; i <= len ; ++ i) {
42             if (s[i] > d[cnt]) d[++cnt] = s[i] ;
43             else {
44                 int pos = lower_bound(d+1,d+1+cnt,s[i]) - d ;
45                 d[pos] = s[i] ;
46             }
47         }
48         printf("%d\n",cnt) ;
49     }
50     return 0 ;
51 }
CROSShh

 

3-3. 题意:有两台机器处理N个任务,任务i在如果机器A上处理要花$ a_{i} $时间,在B花$ b_{i} $时间,两台机器可以同时工作,同一个任务只处理一次即可。求最少要花多长时间处理所有任务。

  任务 i 要么在 A 处理,要么在 B 处理,我们考虑前 i-1 个任务已经处理了,机器 A 的结束时间为 TimeA , 机器 B 的结束时间为 TimeB,那么,

  1. 在 A 处理总的结束时间为 max(TimeA+$ a_{i} $,TimeB}。
  2. 在 B 处理总的结束时间为 max(TimeB+$ b_{i} $,TimeA}。

  当然选最小的啦(对于第一个任务来说TimeA=TimeB=0)。代码略==有空再写吧!

3-4. 题意:设有 N 种不同面值的硬币,记为T[i],现在用这些硬币来找钱,各种硬币个数不限

  Q_A:当只用前 i 个硬币时,可以找出钱数 j 的最少硬币个数记为C(i,j),找不出则C(i,j) = 无穷大,给出C(i,j)的递归表达式和初始条件。1 << i << N , 1 <= j <= L ;

  Q_B: 设计算法,对于1 <= j <= L,计算出C(n,j),只允许用数组L,T,并给出时间复杂度

  Q_C: 在C(n,j)已知的情况下,设计贪心算法,对钱数 m (m <= L)给出求C(n,m)的办法,时间复杂度应为O(n+C(n,m))

3-5. 用 "<" , "=",把三个数A,B,C依序排列,有13种不同的序关系

  A = B = C , A = B < C , A < B = C , A < B < C , A < C < B

  A = C < B , B < A = C , B < A < C ,B < C < A , B = C < A

  C < A = B , C < A < B,C < B < A

现在有 n 个数,问有多少种序关系(时间复杂度要求O(n^2),空间复杂度要求O(n))

3-6. 暂无

3-7. 暂无

3-8. 题意:给出A,B两个字符串,目的是把转换成B,问最小的操作次数,满足以下三种操作:

  1.  删除一个字符 
  2.  插入一个字符
  3.  把一个字符变成另一个字符

 

 题目说的操作我理解为只能对A操作,那么,必须要满足:

  1.  能不操作的就尽量不操作
  2.  能改变的就不使用删除和插入操作

 所以,答案就是max(A.length,B.length) - LCSlength(A,B).

3-9. 题意:经典的石子合并问题,可以用四边形优化到平方

  参考链接:ACdreamer石子合并问题

  和矩阵连乘是同样的类型:dp[i][j] = max(dp[i][k] + dp[k+1][j]+sum[i][j])。sum[i][j] 表示从 i 到 j 的石子的总个数

   我更青睐于在最后一堆石子后面添加 N 堆石子,这样只需要找到max(dp[i][i+N-1]),也是一样的。

3-10. 题意:数塔(数字三角形)

  自顶向上递推即可dp[i][j] += max(dp[i+1][j],dp[i+1][j+1]),注意一下边界

3-11. 题意:完全背包

  参考链接:背包九讲  (提取码:d16f)

for i = 1 ; i <= N ; ++ i
for v = cost[i] ; v <= vmax ; v ++
dp[v] = max(dp[v],dp[v-v[i]]+value[i])

 

  

3-12. 题意:二维费用的背包,上个题目的资料中有!

  dp[i][v][d] = max(dp[i-1][v][d],dp[i][v-v[i]][d-d[i]] + val[i])

3-13. 给了一个特殊的乘法表:

  

== a b c
a b b a
b c b a
c a c c

即:aa = b,ab = b ,ac = a , ba = c,bb = b ,bc = a,ca = a,cb = c,cc = c;

  让干的是:给出一个由abc组成的字符串,问加括号后最终是 a 的方案数.类似矩阵连乘

  dp[a][i][j] = dp[a][i][k]*dp[c][k+1][j] + dp[b][i][k]*dp[c][k+1][j] + dp[c][i][k] + dp[a][k+1][j]

  dp[b][i][j] = dp[a][i][k]*dp[a][k+1][j] + dp[a][i][k]*dp[b][k+1][j] + dp[b][i][k]*dp[b][k+1][j]

  dp[c][i][j] = dp[b][i][k]*dp[a][k+1][j] + dp[c][i][k]*dp[b][k+1][j] + dp[c][i][k]*dp[c][k+1][j]

3-14. 暂无

3-15. 暂无

3-16. 给定一个N*N的网格,左上角为起点 S (1,1),一辆汽车要从左上角走到右下角(只能走网格边),遵循以下规则:

  1.  满油能走的距离是 K ,
  2.  若逆向(X 或 Y 坐标减小)行驶花费 B 
  3.  遇油库就加满油,花费 A
  4.  可以任意增设油库,花费 C (不含加油费)

目的是从左上角走到右下角且花费最小.

dis[i][j]表示从上次满油状态走到位置(i,j)的距离

dp[i][j] 表示走到位置(i,j)的最小花费.

 

dp[i][j] = min(dp[i][j-1],dp[i-1][j],dp[i+1][j] + B,dp[i][j+1] + B) ;

dis[i][j] = dis[x][y] ++ ;//x , y 为dp中选择的i,j

if (i,j) 是个油库,dp[i][j] += A , dis[i][j] = 0 ;

else if dis[i][j] == k {

  //新建油库且加油

  dp[i][j] += (A+C)

  dis[i][j] = 0 ;

}

3-17. 题意:给定一个 M*N 的网格,目的是从左上角到右下角,网格边有权值,某些网格点处有障碍物不能走,设计算法,求路径的最小权值和

  类似3-16,不能走设为无穷大,

  if (dp[i][j] == inf) continue;

  else dp[i][j] = min(dp[i][j-1] + val[][],dp[i][j+1]+val[][],dp[i-1][j]+val[][],dp[i+1][j]+val[][])

3-18. 关于整数的二元运算符"#"定义为:

(X # Y) = 十进制整数 X 的各位数字之和 * 十进制整数 Y 中最大的数字 + Y 中的最小数字

例如:(9 # 30) = 9*3 + 0 = 27;

  问题:对于给定的十进制整数 X 和 K,由X 和 #运算可以组成各种不同的表达式,计算由 X 和 # 运算组成的值为 K 的表达式至少需要多少个 #

    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~end~

第三章算法作业(求助攻)

标签:

原文地址:http://www.cnblogs.com/smile-0/p/5402997.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!