hdu分类 Dynamic Programming(这是一场漫长的旅途)

下面是difficulty 1的题

1003   Max Sum

最长递增子序列。非常经典,最棒的解法是在线算法O(n)的复杂度。

贴的呢,是用dp做的代码。

先是一个高亮的dp递推式,然后找到最大处,用k记录。即所求的子序列的结尾,之后倒推,用减法推出子序列的开头位置。

要注意的点就是各个变量的初始化,初始化不好,很容易WA。还有找子序列的头的时候,倒推的时候找到等值的数是不跳出的,但是更新gx的值,因为0的存在。

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 int a[100005];
 5 int dp[100005];
 6 int main()
 7 {
 8     int t;
 9     cin>>t;
10     int p=1;
11     while(t--)
12     {
13          int n;
14          cin>>n;
15          for(int i=1;i<=n;i++)
16          {
17              cin>>a[i];
18          }
19          memset(dp,0,sizeof(dp));
20          for(int i=1;i<=n;i++)
21 {
22              if(dp[i-1]<0)
23                 dp[i]=a[i];
24              else
25                 dp[i]=dp[i-1]+a[i];
26 }
27
28          int ans=dp[1],k=1;
29          for(int i=1;i<=n;i++)
30          {
31              if(dp[i]>ans)
32              {
33                  ans=dp[i];
34                  k=i;
35              }
36          }
37          int max=ans;
38          int gx=k,sx=k;
39          for(int i=k;i>=1;i--)
40          {
41              max-=a[i];
42              if(max==0) sx=i;
43          }
44
45          cout<<"Case "<<p++<<":"<<endl;
46          cout<<ans<<" "<<sx<<" "<<gx<<endl;
47          if(t!=0) cout<<endl;
48     }
49     return 0;
50 }

1025   Constructing Roads In JGShining‘s Kingdom

这道题也是非常非常经典的,重点是怎么去想到这是一个LIS。

你把一条轴上的看成数组的下标,一条轴上的看成数组的值,一一对应起来,发现它所要求的就是该数组中的LIS。

这里写的是nlogn的LIS的方法。具体的可以看看书或者网上的博客,LIS本来朴素的做法是n²的,但是当你换一个方式dp,dp[n]表示的是长度为n+1的子序列的结尾的最大值。就可以降到nlogn。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 500000+50;
 6 const int INF = 0x3f3f3f3f;
 7 int road[maxn],dp[maxn];
 8 int main()
 9 {
10     int n,x,y;
11     int p = 1;
12     while(~scanf("%d",&n))
13     {
14         for(int i=0;i<n;i++)
15             dp[i] = INF;
16         for(int i=0;i<n;i++)
17         {
18             scanf("%d%d",&x,&y);
19             road[x] = y;
20         }
21         for(int i=1;i<=n;i++)
22         {
23             *lower_bound(dp,dp+n,road[i]) = road[i];
24         }
25         int len = lower_bound(dp,dp+n,INF) - dp;
26
27         printf("Case %d:\n",p++);
28         printf("My king, at most %d road",len);
29         if(len!=1) printf("s");
30         printf(" can be built.\n\n");
31     }
32     return 0;
33 }

1058   Humble Numbers

这道题比较恶心的是输出,英文的序数词的格式orz。

这段dp也比较奇特,对当时的我来说。

 1 int i=1,p2=1,p3=1,p5=1,p7=1;
 2 rec[i++] = 1;
 3 while(i<=5842)
 4 {
 5     int one = min(2*rec[p2],3*rec[p3]);
 6     int two = min(5*rec[p5],7*rec[p7]);
 7     rec[i] = min( one , two );
 8     if(rec[i] == 2*rec[p2]) p2++;
 9     if(rec[i] == 3*rec[p3]) p3++;
10     if(rec[i] == 5*rec[p5]) p5++;
11     if(rec[i] == 7*rec[p7]) p7++;
12     i++;
13 }
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4
 5 int rec[6000];
 6 int main()
 7 {
 8     int i=1,p2=1,p3=1,p5=1,p7=1;
 9     rec[i++] = 1;
10     while(i<=5842)
11     {
12         int one = min(2*rec[p2],3*rec[p3]);
13         int two = min(5*rec[p5],7*rec[p7]);
14         rec[i] = min( one , two );
15         if(rec[i] == 2*rec[p2]) p2++;
16         if(rec[i] == 3*rec[p3]) p3++;
17         if(rec[i] == 5*rec[p5]) p5++;
18         if(rec[i] == 7*rec[p7]) p7++;
19         i++;
20     }
21     int n;
22     while(~scanf("%d",&n) && n)
23     {
24         if(n%10 == 1 && n%100 != 11)
25             printf("The %dst humble number is %d.\n",n,rec[n]);
26         else if(n%10 == 2 && n%100 != 12)
27             printf("The %dnd humble number is %d.\n",n,rec[n]);
28         else if(n%10 == 3 && n%100 != 13)
29             printf("The %drd humble number is %d.\n",n,rec[n]);
30         else
31             printf("The %dth humble number is %d.\n",n,rec[n]);
32     }
33     return 0;
34 }

1059   Dividing

时间: 2024-12-05 07:39:31

hdu分类 Dynamic Programming(这是一场漫长的旅途)的相关文章

hdu 4223 Dynamic Programming?

Dynamic Programming? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Dynamic Programming, short for DP, is the favorite of iSea. It is a method for solving complex problems by breaking them down

hdu 4223 Dynamic Programming? (dp)

//连续的和的绝对值最小 # include <stdio.h> # include <string.h> # include <algorithm> # include <math.h> using namespace std; int main() { int t,i,j,num,n,min1; int sum[1010],a[1010]; int cas=0; while(~scanf("%d",&t)) { while(t

hdu 4972 A simple dynamic programming problem(高效)

题目链接:hdu 4972 A simple dynamic programming problem 题目大意:两支球队进行篮球比赛,每进一次球后更新比分牌,比分牌的计数方法是记录两队比分差的绝对值,每次进球的分可能是1,2,3分.给定比赛中的计分情况,问说最后比分有多少种情况. 解题思路:分类讨论: 相邻计分为1-2或者2-1的时候,会对应有两种的的分情况 相邻计分之差大于3或者说相等并且不等于1的话,为非法输入 其他情况下,不会造成新的比分情况产生 对于最后一次比分差为0的情况,就没有谁赢谁

HDU 4972 A simple dynamic programming problem(推理)

HDU 4972 A simple dynamic programming problem 题目链接 推理,会发现只有前一个和当前一个分数为(1, 2)或(2, 1)的时候,会有两种加分方法,其他情况最多就一种情况,所以只要统计(1, 2),(2, 1)的个数,最后判断分差是否为0,如果不为0,那么可能是正或负,那就是两倍 代码: #include <cstdio> #include <cstring> const int N = 100005; int t, n, a[N]; i

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

HDU-4972 A simple dynamic programming problem

http://acm.hdu.edu.cn/showproblem.php?pid=4972 ++和+1还是有区别的,不可大意. A simple dynamic programming problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 307    Accepted Submission(s): 117 Problem D

2016 UESTC Training for Dynamic Programming

2016 UESTC Training for Dynamic Programming A - 柱爷与咸鱼神功 题意: 柱爷有n(<=5000)点心情去学m(<=5000)个招式,每个招式会得到一定的修炼值,但要消耗一定的心情,求最多的修炼值. 题解: 0.这是一个裸的背包问题,用每一个物品去更新每一种背包的状态. 1.状态定义:dp[i]表示用i点心情得到的最多修炼值. 2.状态转移:dp[i] = max{dp[i-v[j]]+w[j]} 代码: 1 2 3 4 5 6 7 8 9 10

Dynamic Programming

We began our study of algorithmic techniques with greedy algorithms, which in some sense form the most natural approach to algorithm design. Faced with a new computational problem, we've seen that it's not hard to propose multiple possible greedy alg

Dynamic Programming | Set 3 (Longest Increasing Subsequence)

在 Dynamic Programming | Set 1 (Overlapping Subproblems Property) 和 Dynamic Programming | Set 2 (Optimal Substructure Property) 中我们已经讨论了重叠子问题和最优子结构性质,现在我们来看一个可以使用动态规划来解决的问题:最长上升子序列(Longest Increasing Subsequence(LIS)). 最长上升子序列问题,致力于在一个给定的序列中找到一个最长的子序列