模板1

最优子矩阵

 1 /*对于一个矩阵而言,如果我们将连续k行的元素纵向相加,并对相加后所得的数列求连续最大和,则此连
 2 
 3 续最大和就是一个行数为k的最优子矩阵!
 4 */
 5 
 6 #include<iostream>
 7 using namespace std;
 8 int rec[101][101];
 9 //int m=0;
10 //void get(int ans[101],int nums)
11 //{
12 //    int b = 0;
13 //    for(int i=0;i<nums;i++)
14 //    {
15 //        if(b<0)
16 //            b = ans[i];
17 //        else
18 //            b +=ans[i];
19 //        if(b>m)
20 //            m = b;
21 //    }
22 //}
23 int main()
24 {
25     int nums;
26     int result[101];
27     cin>>nums;
28     int m=0;
29     for(int i=0;i<nums;i++)
30     {
31         for(int j=0;j<nums;j++)
32         {
33             cin>>rec[i][j];
34         }
35     }
36     for(int i=0;i<nums;i++)
37     {
38         memset(result,0,sizeof(result));
39         for(int j=i;j<nums;j++)
40         {            
41             int b = 0;
42             for(int k=0;k<=nums;k++)
43             {
44                 result[k]+=rec[j][k];
45                 if(b<=0)
46                     b = result[k];
47                 else
48                     b +=result[k];
49                 if(b>m)
50                     m=b;
51             }
52 
53         }
54     }
55     cout<<m<<endl;
56     return 0;
57 }
View Code

括号匹配

 1 /*
 2 括号匹配问题
 3 前i个中 ) 的个数为 j个。
 4 初始化,dp[1][0]=1;
 5 
 6 设立 j 为 ) 比 ( 更加简单
 7 
 8 */
 9 
10 #include<stdio.h>
11 int dp[20][20];
12 
13 int main()
14 {
15     int i,j,n;
16     while(scanf("%d",&n)>0)
17     {
18         if(n%2==1)
19         {
20             printf("0\n");
21             continue;
22         }
23         dp[1][0]=1;
24         for(i=2;i<=n;i++)
25         {
26             for(j=0;j<=i/2;j++)
27             {
28                 dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
29             }
30         }
31         printf("%d\n",dp[n][n/2]);
32     }
33     return 0;
34 }
View Code

RMQ

 1 /*
 2 
 3 RMQ 求解区间最值问题。
 4 
 5   满足动态规范方程:
 6   dp[i][j]=min{ dp[i][j-1],dp[i+( 1<<(j-1) )][j-1]  }
 7   利用的是二分的思想,表示dp[i][j],位置i开始,长度为j的最值
 8   分解成,dp[i][j-1] ,dp[i+( 1<<(j-1) )][j-1]
 9 
10 */
11 
12 #include<iostream>
13 #include<cstdlib>
14 #include<cstring>
15 #define N 1000
16 using namespace std;
17 
18 int dp[N][N];
19 int A[N];
20 
21 int hmin(int x,int y)
22 {
23     return x>y? x:y;
24 }
25 
26 int RMQ(int L,int R) //查询的操作
27 {
28     int k=0;
29     while(  (1<<(k+1))<=R-L+1 )k++;
30     return hmin(dp[L][k-1],dp[L+(1<<(k-1))][k-1]);
31 }
32 
33 void make_ini(int n)
34 {
35     int i,j,L,R,M;
36     for(i=1;i<=n;i++)  //初始化
37         dp[0][i]=A[i];
38 
39     for(j=1;(1<<j)<=n;j++) //元素编号从 1 到 n
40         for(i=1;i+j-1<=n;i++)
41             dp[i][j]=hmin(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
42 
43 /*
44     P198    
45         
46 */
47     scanf("%d",&M);
48     while(M--)
49     {
50         scanf("%d%d",&L,&R);
51         printf("%d\n",RMQ(L,R));
52     }
53 }
54 
55 int main()
56 {
57     int n,i;
58     while(scanf("%d",&n)>0)
59     {
60         for(i=1;i<=n;i++)
61             scanf("%d",&A[i]);
62         make_ini(n);
63     }
64     return 0;
65 }
View Code

求二进制数中1的个数

 1 #include<stdio.h>
 2 int get(int i)
 3 {
 4     int count=0;
 5     while(i)
 6     {
 7         ++count;
 8         i=(i-1)&i;
 9     }
10     return count;
11 }
12 int main()
13 {
14     int i;
15     while(scanf("%d",&i)>0)
16     {
17         printf("%d\n",get(i));
18     }
19 }
View Code

线段切割

 1 /*
 2 看了中学生的论文,
 3 学 线段切割
 4 
 5 
 6 线段
 7 a. ___________________.b
 8   
 9     c.___________.d
10      
11 */
12 
13 struct Line
14 {
15     int a;    //线段起始点
16     int b;    //线段终点
17     int longint; //长度
18 };
19 
20 bool Function(int a,int b,int c,int d) 
21 {
22     if(a>=d || c>=b) return false;
23     else return true;
24 }
25 //判断线段是否重叠。当满足a>=d || c>=b的时候,不满足.
26 
27 
28 
29 void Cut(int Num,int c,int d)
30 {
31     if(Line[Num].a<c) Add(Line[Num].a,c);
32     if(d<Line[Num].b) Add(d,Line[Num].b);
33     Delete(Num);
34 }
35 //切割线段过程。如最上方所示。
36 
37 /*
38 线段
39 a. ___________________.b
40   
41     c.___________.d
42 */
43 
44 
45 void Add(int a,int b)
46 {
47     total++;
48     Line[total].a=a;
49     Line[total].b=b;
50 }
51 //将一条线段增加到线段集合中
52 
53 
54 void Delete(int Num)
55 {
56     Line[Num]=Line[total];
57     total--;
58 }
59 //线段的删除过程,可以将集合中最后一天线段
60 //移到要删除线段的位置
View Code

石子合并

 1 /*
 2 f(n3)超时,超空间。
 3 */
 4 
 5 #include<stdio.h>
 6 #include<stdlib.h>
 7 int dp[10005][10005];
 8 int sum[10005]={0};
 9 int a[10005];
10 int mmin(int x,int y)
11 {
12     if(x<y)
13         return x;
14     else return y;
15 }
16 int main()
17 {
18     int n,i,j,k,len;
19     while(scanf("%d",&n)>0)
20     {
21         if(n==0)break;
22         for(i=1;i<=n;i++)
23         {
24             scanf("%d",&a[i]);
25             sum[i]=sum[i-1]+a[i];
26         }
27         for(len=2;len<=n;len++)//长度
28         {
29             for(i=1;i<=n-len+1;i++) //起点
30             {
31                 j=i+len-1; //终点
32                 dp[i][j]=0x7fff;
33                 for(k=1;k<j;k++)
34                     dp[i][j]=mmin(dp[i][j],dp[i][k]+dp[k+1][j]-sum[i-1]+sum[j]);
35             }
36         }
37         printf("%d\n",dp[1][n]);
38     }
39     return 0;
40 }
View Code

 

posted @ 2013-09-10 20:14  芷水  阅读(158)  评论(0编辑  收藏  举报