hdu 4561 (dp做法 || 非dp做法)

题目:

Problem Description

小明和他的好朋友小西在玩一个游戏,由电脑随机生成一个由-2,0,2三个数组成的数组,并且约定,谁先算出这个数组中某一段连续元素的积的最大值,就算谁赢!

比如我们有如下随机数组:

2 2 0 -2 0 2 2 -2 -2 0 

在这个数组的众多连续子序列中,2 2 -2 -2这个连续子序列的积为最大。

现在小明请你帮忙算出这个最大值。
Input
第一行输入一个正整数T,表示总共有T组数据(T <= 200)。
接下来的T组数据,每组数据第一行输入N,表示数组的元素总个数(1<= N <= 10000)。
再接下来输入N个由0,-2,2组成的元素,元素之间用空格分开。
Output
对于每组数据,先输出Case数。
如果最终的答案小于等于0,直接输出0
否则若答案是2^x ,输出x即可。
每组数据占一行,具体输出格式参见样例
 
Sample Input
2 2 -2 0 10 2 2 0 -2 0 2 2 -2 -2 0
 
Sample Output
Case #1: 0
Case #2: 4
 
非dp做法:
 
      思路:  把0看成隔板,把那一串数分成许多段,之后再计算每一小段里面最多有几个数的连续乘积是整数,再取一个最大值。
 
代码
 1 #include<stdio.h>
 2 #include<string.h>
 3 int main()
 4 {
 5     int N;
 6     int n,m,i,j,max,flag=0,flag1=0;
 7     
 8     int symbol[10005]; //标记当前位置的数 与之前的连续不为0的数 的乘积 的正负;
 9     
10     int num[10005];   // 在当前位置对应的数之前(含这个数)共有 多少个 连续的数的乘积大于0;
11     
12     scanf("%d",&N);
13     for(j=1;j<=N;j++)
14     {
15         scanf("%d",&n);
16         memset(symbol,0,sizeof(symbol));
17         memset(num,0,sizeof(num));
18         symbol[0]=1;flag=0;flag1=0;max=0;
19         for(i=1;i<=n;i++)
20         {
21             scanf("%d",&m);
22             if(m==0)
23             {
24                 symbol[i]=1;
25                 num[i]=0;
26                 flag=0;
27                 flag1=0;
28             }
29             else
30             {
31                 if(flag1==0) flag1=i;   // 记录从一个不为0的数的位置
32                 if(m<0)
33                 {
34                     if(flag==0) flag=i; //记录 这一段不为0的数中 第一个为负值的数的 位置
35                 }
36                 symbol[i]=symbol[i-1]*m/2;
37                 
38                 if(symbol[i]>0) num[i]=i+1-flag1;  
39                 else
40                 {
41                     if(flag==0) num[i]=i+1-flag1;
42                     else num[i]=i+1-flag1-num[flag]; 
43                 }
44                 if(num[i]>max&&i>flag) max=num[i];
45             }
46         }
47         printf("Case #%d: %d\n",j,max);    
48     }
49 }
View Code

dp 做法:

         思路负负得正,正正得正 ,正负得负。

                dp[1][i]表示 含当前位置的数的 连续乘积为正的数的个数;dp[0][i]表示 含当前位置的数的 连续乘积为负的数的个数

代码:

 

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

 

 

 

posted @ 2013-06-10 18:38  lysr__tlp  阅读(261)  评论(0编辑  收藏  举报