Poj--1952(DP,计数)

本文解析了一道涉及数列的动态规划题目,通过实例详细介绍了如何利用动态规划求解最长递增子序列问题,并特别关注了数值重复情况下计数方式的特殊处理。

2014-12-11 21:35:26

思路:首先... 本题的数据比较水,按理说应该用高精度的... 不过long long 可过... 

  本来以为是个水dp,后来怎么搞都wa,再后来仔细看题意。。。原来不是按照数的不同位置来计数,而是数的值,比如5个数2 2 2 1 1,答案是2 1 (- -就一种)

  所以如果按照正常的LDS转移后,对于dp[i],前面dp[j](1<=j<i)出现了几个相同值(即dp[j]==dp[i] , val[i] == val[j])那么只能保留最后的那个(为什么保留最后的呢,因为最后的计数最全,如果保留前面会导致丢失),所以扫一遍前面相同的dp,赋值为0。

 1 /*************************************************************************
 2     > File Name: 1952.cpp
 3     > Author: Natureal
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Thu 11 Dec 2014 06:00:11 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int N;
28 struct node{
29     int v,dp;
30     ll num;
31 }t[5010];
32 
33 int main(){
34     scanf("%d",&N);
35     for(int i = 1; i <= N; ++i){
36         scanf("%d",&t[i].v);
37     }
38     int tmax = -1;
39     for(int i = 1; i <= N; ++i){
40         t[i].dp = 1;
41         t[i].num = 1;
42         for(int j = 1; j < i; ++j) if(t[i].v < t[j].v){
43             if(t[j].dp + 1 > t[i].dp){
44                 t[i].dp = t[j].dp + 1;
45                 t[i].num = t[j].num;
46             }
47             else if(t[j].dp + 1 == t[i].dp){
48                 t[i].num += t[j].num;
49             }
50         }
51         for(int j = i - 1; j >= 1; --j){
52             if(t[j].v == t[i].v && t[j].dp == t[i].dp){
53                 t[j].num = 0;
54                 break;
55             }
56         }
57         tmax = max(tmax,t[i].dp);
58     }
59     ll ans = 0;
60     for(int i = 1; i <= N; ++i){
61         if(t[i].dp == tmax){
62             ans += t[i].num;
63         }
64     }
65     printf("%d %I64d\n",tmax,ans);
66     return 0;
67 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4158569.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值