2012.7.25 模版

来源:互联网 发布:java = 编辑:程序博客网 时间:2024/06/06 08:33

char -128 ~ +127 (1 Byte)
short -32767 ~ + 32768 (2 Bytes)
unsigned short 0 ~ 65536 (2 Bytes)
int -2147483648 ~ +2147483647 (4 Bytes)
unsigned int 0 ~ 4294967295 (4 Bytes)
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes)
double 1.7 * 10^308 (8 Bytes)

unsigned int 04294967295
long long
的最大值:
9223372036854775807
long long的最小值:
-9223372036854775808
unsigned long long的最大值:1844674407370955161

__int64的最大值:9223372036854775807
__int64
的最小值:
-9223372036854775808
unsigned __int64的最大值:18446744073709551615

 

卡特兰数:

1 通项公式:h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!)

2递推公式:h(n)=((4*n-2)/(n+1))*h(n-1); h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0).

3前几项为:h(0)=1,h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,......

 

#include<iostream>

using namespace std;

int a[101][101]={0};

int main()

{

    int n,i,j,len,r,temp,t;

    int b[101];

    a[1][0] = 1;

    len = 1;

    b[1] = 1;

    for(i=2;i<=100;i++)

    {

        t = i-1;

        for(j=0;j<len;j++) //乘法

            a[i][j] = a[i-1][j]*(4*t+2);

        for(r=j=0;j<len;j++)  //处理相乘结果

        {

            temp = a[i][j] + r;

            a[i][j] = temp % 10;

            r = temp / 10;

        }

        while(r) //进位处理

        {

            a[i][len++] = r % 10;

            r /= 10;

        }

 

        for(j=len-1,r=0;j>=0;j--) //除法

        {

            temp = r*10 + a[i][j];

            a[i][j] = temp/(t+2);

            r = temp%(t+2);

        }

        while(!a[i][len-1]) //高位零处理

            len --;

        b[i] = len;

    }

    while(cin>>n)

    {  

        for(j=b[n]-1;j>=0;j--)

            printf("%d",a[n][j]);

        printf("\n");

    }

    return 0;

}

 

KMP算法

int get_nextval(SString T,int &nextval[ ]){
          
i=1; nextval[1]=0; j=0;
          
while(i<T[0]){
              
if(j==0||T[i]==T[j]){
                  
++i;++j;
                  
if (T[i]!=T[j]) nextval[i]=j;
                  
else nextval[i]=nextval[j];
              
}
              
else j=nextval[j];
          
}
       }

 

欧拉函数

C语言:

  int eular(int n)

  {

  int ret=1,i;

  for(i=2;i*i<=n;i++)

  if(n%i==0)

  {

  n/=i,ret*=i-1;

  while(n%i==0)

  n/=i,ret*=i;

  }

  if(n>1)

  ret*=n-1;

  return ret;

}

 

#include <stdlib.h>

  #define N 10000000

  main()

  {

  int *phi,i,j;

  char *prime;

  prime=(char*)malloc((N+1)*sizeof(char));

  prime[0]=prime[1]=0;

  for(i=2;i<=N;i++)

  {

  prime[i]=1;

  }

  for(i=2;i*i<=N;i++)

  {

  if(prime[i])

  {

  for(j=i*i;j<=N;j+=i)

  {

  prime[j]=0;

  }

  }

  } //这段求出了N内的所有素数

  phi=(int*)malloc((N+1)*sizeof(int));

  for(i=1;i<=N;i++)

  {

  phi[i]=i;

  }

  for(i=2;i<=N;i++)

  {

  if(prime[i])

  {

  for(j=i;j<=N;j+=i)

  {

  phi[j]=phi[j]/i*(i-1); //此处注意先/i再*(i-1),否则范围较大时会溢出

  }

  }

 

 

欧几里德算法的C++语言描述

  int Gcd(int a, int b)

  {

  if(b == 0)

  return a;

  return Gcd(b, a % b);

  }

 

 

扩展欧几里德定理

int exGcd(int a, int b, int &x, int &y)

  {

  if(b == 0)

  {

  x = 1;

  y = 0;

  return a;

  }

  int r = exGcd(b, a % b, x, y);

  int t = x;

  x = y;

  y = t - a / b * y;

  return r;

  }

 

p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整数解满足:

  p = p1 + b/Gcd(a, b) * t

  q = q1 - a/Gcd(a, b) * t(其中t为任意整数)

p 、q就是p * a+q * b = c的所有整数解。

 

 

约瑟夫环

 #include <stdio.h>

  int main(void)

  {

  int n, m, i, s=0;

  printf ("N M = ");

  scanf("%d%d", &n, &m);

  for (i=2; i<=n; i++)

  s=(s+m)%i;

  printf ("The winner is %d\n", s);

  return 0 ;

  }

 

汉诺塔

    #include<stdio.h>

int k,n;

void hanoi(int n,char x,char y,char z)

{

         if(n==1) k++,printf("%c->%c\n",x,z);

         else

         {

             hanoi(n-1,x,z,y);

             k++,printf("%c->%c\n",x,z);

             hanoi(n-1,y,x,z);

         }

}

int main()

{

          while(~scanf("%d",&n))

          {

              k=0,hanoi(n,'1','2','3');    

                     printf("sumstep=%d\n",k);             

          }

}

 

二分算法

while (low < high)    //返回刚好比a大的位置

                  {

                  mid = (low + high)/2;

                  if (a < b[mid])

                     high = mid ;

                  else if (a > b[mid])

                     low = mid + 1;

                  else if(a == b[mid])

                   break;

            }

                  return low

 

 

 

斐波拉契数列

F(n)=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}

F(n) = [ (( sqrt ( 5 ) + 1 ) / 2) ^ n ]其中[ x ]表示取距离 x 最近的整数。

从第二项开始,每个奇数项的平方都比前后两项之积多1,每个偶数项的平方都比前后两项之积少1

{f(n), f(n-1), f(n-1), f(n-2)} ={1, 1, 1,0}n-1

f(m+n-1)=f(m-1·f(n-1)+f(m·f(n)。

Fib[n+2]-1 = Fib[1]+Fib[2]+...Fib[n]

 

A^B%C

unsigned mod(unsigned x, unsigned y,unsigned n)

{  

unsigned s=1;     

  while(y)

{  

   if(y&1)             // a^b=(a*a)^(b/2)*a^(y&1)

   s=(s*x)%n;

   y>>=1;  

   x=(x*x)%n;  

  }  

  return s;

}

 

Coj 1053斐波拉契数列+矩阵连乘

#include<stdio.h>

const int N=2;

long long a,b,p;

long long fib(long long n)

{

    long long f[2][2]={{1,1},{1,0}},g[2][2]={{1,0},{0,1}},h[2][2];

    int i,j,k;

    while(n>0)

    {

       if(n&1)

       {

         for(i=0;i<N;i++)

            for(j=0;j<N;j++)

               for(h[i][j]=k=0;k<N;k++)

                  h[i][j]+=f[i][k]*g[k][j];

         for(i=0;i<N;i++)

            for(j=0;j<N;j++)

               g[i][j]=h[i][j]%p;

       }

       for(i=0;i<N;i++)

            for(j=0;j<N;j++)

               for(h[i][j]=k=0;k<N;k++)

                  h[i][j]+=f[i][k]*f[k][j];

       for(i=0;i<N;i++)

            for(j=0;j<N;j++)

               f[i][j]=h[i][j]%p;   

       n>>=1;

    }

    return g[0][1];

}

int main()

{

    int r;

    while(scanf("%lld%lld%lld",&a,&b,&p)!=EOF)

    {

     

      a=fib(a+1);

      b=fib(b+2);  

      b=(b-a+p)%p,r=p,a=1;

      while(r)

      {

        if(r&1) a=(a*b)%p;

        b=(b*b)%p;

        r>>=1;

      } 

      printf("%I64d\n",a);   

    }

}

 

 

 

 

 

 

 

 

正整数n的因子之和

n=p1e1p2e2…prer

Sum=(1+p1+p12+…+p1e1)*(1+p2+p22+…+p2e2) *…*(1+pr+pr2+…+prer)

 

 

gcd Stein算法

int gcd(int a, int b)

{  

       if(a==0)

          return b;  

       if(b == 0) return a;  

       if(a%2==0&&b%2==0)

           return 2*gcd(a>>1,b>>1);  

       else if(a%2==0) 

           return gcd(a>>1,b);  

       else if(b%2==0)

           return gcd(a,b>>1);  

       else

           return gcd(abs(a-b),Min(a,b));

}

 

 

DP

母函数模版

#include<iostream>

#include<stdio.h>

using namespace std;

const int maxn=121;

int main()

{

    int c[maxn],d[maxn];

    int i,j,k;

    for(i=0;i<maxn;i++)

    c[i]=1,d[i]=0;

    for(i=2;i<maxn;i++)

    {

       for(j=0;j<maxn;j++)

       {

          for(k=0;k+j<maxn;k+=i)

          {

             d[j+k]+=c[j];                   

          }               

       }

       for(j=0;j<maxn;j++)

       {

       c[j]=d[j];       

       d[j]=0;

       }      

    }

    while(scanf("%d",&k)!=EOF)

    {

        printf("%d\n",c[k]);  

    }

    return 0;

}

 

 

最长(非)上升子序列

1.二分+贪心

#include<stdio.h>

#include<iostream>

using namespace std;

const int MAX=1001;

 

int main()

{

    int n,i,j,k1,k2,max1,max2;

    int dp1[MAX],dp2[MAX],s[MAX];

    while(~scanf("%d",&n))

    {

       for(i=1;i<=n;i++)

          scanf("%d",s+i);

       dp2[1]=dp1[1]=s[1],max1=max2=k1=k2=1;

       for(i=2;i<=n;i++)

       {

          if(s[i]<=dp1[k1])

          {

             dp1[++k1]=s[i]; 

             max1=k1>max1?k1:max1; 

          }            

          else

          {

             int low=1,high=k1,mid;

             while(low<high)

             {

                mid=(low+high)/2;

                if(dp1[mid]>s[i]-1) low=mid+1;

                else if(dp1[mid]<s[i]) high=mid;    

             }

             dp1[low]=s[i];

             

          }

          if(s[i]>dp2[k2])

          {

             dp2[++k2]=s[i];

             max2=k2>max2?k2:max2;          

          }

          else

          {

              int low=1,high=k2,mid;

              while(low<high)

              {

                 mid=(low+high)/2;

                 if(dp2[mid]>s[i])  high=mid;

                 else if(dp2[mid]<s[i]) low=mid+1;

                 else { low=mid; break; }         

              }

              dp2[low]=s[i];

          }

       }

       printf("%d %d\n",max1,max2);               

    }

}

 

O(n^2)

#include<stdio.h>

#include<iostream>

using namespace std;

const int MAX=30001;

  

int main()

{

    int n,i,j,max1,max2;

    int dp1[MAX],dp2[MAX],s[MAX];

    while(~scanf("%d",&n))

    {

       for(i=1;i<=n;i++)

          scanf("%d",s+i);

       for(i=1;i<=n;i++)

          dp2[i]=dp1[i]=1;

       for(i=2;i<=n;i++)

       {

          for(j=1;j<i;j++)

          {

             if(s[j]>=s[i])

             {

               dp1[i]=dp1[j]+1>dp1[i]?dp1[j]+1:dp1[i];         

             }  

             else 

             {

               dp2[i]=dp2[j]+1>dp2[i]?dp2[j]+1:dp2[i];             

             }          

          }              

       }

       max1=max2=1;   

       for(i=2;i<=n;i++)

       {

          max1=dp1[i]>max1?dp1[i]:max1;

          max2=dp2[i]>max2?dp2[i]:max2;            

       }

       printf("%d %d\n",max1,max2);                

    }

}

最长公共子序列

#include<stdio.h>

#define max(a,b) a > b? a : b

const int MAX=5001;

int i, j, n;

short dp[MAX+1][MAX+1];

char str[MAX+1];

int main()

{

    while( ~scanf("%d",&n) )

    {

       scanf( "%s" , str+1 );

      

       for ( i = 0 ; i <= n ; i++ ) for ( j = 0 ; j <= n ; j++ )  dp[i][j] = 0; 

      

       for ( i = 1 ; i <= n ; i++ ) 

           for ( j = n ; j > 0 ; j-- )

           {

               dp[i][n-j+1] = str[i] == str[j]? dp[i-1][n-j]+1 : max( dp[i-1][n-j+1] , dp[i][n-j] ) ;

           }

          

       printf("%d\n", n-dp[n][n] );

    }

}

 

 

 

 

 

 

 

 

背包九讲

0 – 1背包

POJ  3624

#include<iostream>

#include<stdio.h>

using namespace std;

int n,m,i,j;

int w[3410],d[3410],f[12881];

int main()

{

    while(~scanf("%d%d",&n,&m))

    {

        for(i=1;i<=n;i++)

         scanf("%d %d",&w[i],&d[i]);

        for(i=0;i<=m;i++)

        f[i]=0;

        for(i=1;i<=n;i++)

        {

           for(j=m;j-w[i]>=0;j--)

           {

            f[j]=f[j]>(f[j-w[i]]+d[i])?f[j]:(f[j-w[i]]+d[i]); 

              if(i==n) break;

           }    

        }

        printf("%d\n",f[m]);

    }

    return 0;

}

 

完全背包

hdu 1114

#include<iostream>
#include<stdio.h>
using namespace std;
#define INF 0x3fffffff
int main()
{
    int cas,e,f,i,j,n,k;
    int p[510],w[510],fu[10010];
    scanf("%d",&cas);
    while(cas--)
    {
       scanf("%d%d",&e,&f);
       f-=e;
       scanf("%d",&n);
       for(i=1;i<=n;i++)
       scanf("%d%d",&p[i],&w[i]);
       fu[0]=0;
       for(i=1;i<=f;i++)
       fu[i]=INF;
       for(i=1;i<=n;i++)
       {
          for(j=w[i];j<=f;j++)
          {
             fu[j]=fu[j]<fu[j-w[i]]+p[i]? fu[j]:fu[j-w[i]]+p[i];
          }               
       }     
       if(fu[f]==INF) printf("This is impossible.\n");
       else printf("The minimum amount of money in the piggy-bank is %d.\n",fu[f]);   
    }
}

 

多重背包

hdu 2191 二进制法

#include<stdio.h>

int main()

{

    int n,m,cas,i,j,num,k;

    int p[110],w[110],s[110],f[110];

    scanf("%d",&cas);

    while(cas--)

    {

       scanf("%d%d",&n,&m);

       for(i=0;i<m;i++)

       scanf("%d%d%d",&p[i],&w[i],&s[i]);

       for(i=0;i<=n;i++) f[i]=0;

       for(i=0;i<m;i++)

       {

          k=1;

          while(k<s[i])

          {

            num=p[i]*k;

            for(j=n;j>=num;j--)

            f[j]=f[j]>(f[j-num]+w[i]*k)?f[j]:f[j-num]+w[i]*k; 

            s[i]-=k;   

            k*=2;     

          } 

          num=p[i]*s[i];

          for(j=n;j>=num;j--)

          f[j]=f[j]>f[j-num]+w[i]*s[i]?f[j]:f[j-num]+w[i]*s[i];            

       }

       printf("%d\n",f[n]);

    }

}

 

单调队列 poj2823

#include "stdio.h"

#include "string.h"

const int M=1000005;

int arr[M];

int Minq[M],Maxq[M];

int Q[M],Inq[M];

int n,k;

void Min()

{

 int head=1,tail=0;

 int i;

 

 for(i=1;i<=n;i++)

 {

  while(head<=tail && Q[tail]>arr[i])

   tail--;

  tail++;

  Q[tail]=arr[i];

  Inq[tail]=i;

  if(i>=k)

  {

   while(Inq[head]<=i-k) head++;

   Minq[i-k]=Q[head];

  }

 }

}   

void Max()

{

   int head=1,tail=0;

   int i;

   for(i=1;i<=n;i++)

   {

      while(head<=tail && Q[tail]<arr[i])

        tail--;

      tail++;

      Q[tail]=arr[i],Inq[tail]=i;

      if(i>=k)

      {

         while(Inq[head]<=i-k)

           head++;

         Maxq[i-k]=Q[head];    

      }             

   } 

}

int main()

{

 while(scanf("%d%d",&n,&k)!=EOF)

 {

  if(k>n) k=n;

  int i;

  for(i=1;i<=n;i++)

   scanf("%d",&arr[i]);

  Min();

  Max();

  for(i=0; i<n-k+1; i++)  

            printf("%d%c", Minq[i], (i < n - k) ? ' ' : '\n');   

        for(i=0; i<n-k+1; i++)  

            printf("%d%c", Maxq[i], (i < n - k) ? ' ' : '\n');    

 }

 return 0;

}

 

单调队列多重背包hdu 2191

#include<stdio.h>

const int N=110;

int main()

{

    int n,m,cas,i,j,k,y,head,tail;

    int p[N],w[N],s[N],f[N],u[N],v[N];

    scanf("%d",&cas);

    while(cas--)

    {

       scanf("%d%d",&n,&m);

       for(i=0;i<m;i++)

       scanf("%d%d%d",&p[i],&w[i],&s[i]);

       for(i=0;i<=n;i++) f[i]=0;

       for(i=0;i<m;i++)

       {

             for(j=0;j<p[i];j++)

             {

                head=0,tail=-1;

                for(k=0;k<=(n-j)/p[i];k++)

                {

                   y=f[j+k*p[i]]-k*w[i];

                   while(head<=tail&&u[tail]<=y) tail--;

//去掉队列中不可能为最大值大数据

                   u[++tail]=y,v[tail]=k;

                   while(head<=tail&&v[tail]-v[head]>s[i]) head++;

                   //保证队列首尾差值数量不大于当前物品的数量

                   f[j+k*p[i]]=u[head]+k*w[i];

                }               

             }        

       }

       printf("%d\n",f[n]);

    }

}

 

二维背包hdu3496

#include<stdio.h>

int cas,n,m,time,i,j,k,t,v;

int f[1010][110];

int main()

{

    scanf("%d",&cas);

    while(cas--)

    {

       scanf("%d%d%d",&n,&m,&time);

       for(i=0;i<=time;i++)

          for(j=0;j<=m;j++)

             f[i][j]=-100000000;

       f[0][0]=0;

       for(i=0;i<n;i++)

       {

          scanf("%d%d",&t,&v);

          for(j=time;j>=t;j--)

             for(k=m;k>0;k--)

                f[j][k]=f[j-t][k-1]+v>f[j][k]?f[j-t][k-1]+v:f[j][k];        

       }

       for(i=v=0;i<=time;i++) v=f[i][m]>v?f[i][m]:v;

       printf("%d\n",v);

    }

}

 

分组背包hdu1712

#include<stdio.h>

#include<iostream>

using namespace std;

int max(int a,int b)

{

   if(a>b) return a;

   return b;

}

int main()

{

    int n,m,i,j,k,t,c;

    int dp[110],w[110];

    while(~scanf("%d%d",&n,&m),n||m)

    {

       for(i=0;i<=m;i++) dp[i]=0;

       for(i=1;i<=n;i++)

       {

          for(j=1;j<=m;j++)

             scanf("%d",&w[j]);  

          for(k=m;k>=0;k--)

             for(j=1;j<=m;j++)

             {

                if(k-j>=0) dp[k]=max(dp[k],dp[k-j]+w[j]);            

             }

       }    

       printf("%d\n",dp[m]);           

    }

    return 0;

}

 

分组背包 每组至少选择一个 状态转移方程 如下:

dp[i][t]=max(dp[i][t],dp[i][t-p[i][j]]+v[i][j]);

dp[i][t]=max(dp[i][t],dp[i-1][t-p[i][j]]+v[i][j]);

 

依赖背包

1.转化为分组背包方法  NOIP2006金明的预算方案

#include <iostream>  

#include <cmath>    

using namespace std; 

struct node { 

    int v,p,q;          

}data[61];        

int n, m, _max; 

int ans[32001],f[60][32001]; 

int main() { 

    while(scanf("%d%d",&n,&m)!=EOF)

    { 

        memset(f, -1, sizeof(f)); 

        f[0][0] = 0; 

        n /= 10; 

        for(int i = 1; i <= m; i++)

        { 

            scanf("%d%d%d",&data[i].v,&data[i].p,&data[i].q); 

            data[i].v /= 10,data[i].p*=data[i].v;

            f[i][0] = 0; 

        } 

        for(int i = 1; i <= m; i++)

        { 

            if(data[i].q == 0) continue; 

            for(int j = n; j >= data[i].v; j--)

            { 

                if(f[data[i].q][j - data[i].v] != -1)

  f[data[i].q][j]=max(f[data[i].q][j],f[data[i].q][j-data[i].v]+data[i].p);

            } 

        } 

        for(int i = 1; i <= m; i++)

        { 

            if(data[i].q != 0) continue; 

            for(int j = n; j >= 0; j--)

            { 

                if(f[i][j] != -1)

                { 

                    if(j + data[i].v <= n)

  f[i][j + data[i].v] = max(f[i][j + data[i].v], f[i][j] + data[i].p);

                    f[i][j] = -1; 

                } 

            } 

        }  

        memset(ans, -1, sizeof(ans)); 

        ans[0] = _max = 0; 

        for(int i = 1; i <= m; i++) { 

            if(data[i].q != 0) continue; 

            for(int j = n; j >= data[i].v; j--) { 

                for(int k = j; k >= data[i].v; k--) { 

                    if(f[i][k] != -1 && ans[j - k] != -1) { 

                        ans[j] = max(ans[j], f[i][k] + ans[j - k]); 

                    } 

                } 

            } 

        }

        for(int i=0;i<=n;i++)

         _max = max(_max, ans[i]);  

        printf("%d\n",_max*10);  

    } 

    return 0; 

 

2. 二附件依赖背包方法

#include<stdio.h>

const int MAX=32001;

const int M=61;

int main()

{

    int n,m,i,j,k,y,max;

    int p[M],q[M],v[M],a[5];

    int dp[MAX];

    while (~scanf("%d %d",&n,&m))

    {

          n/=10;

          for (i=0;i<=n;i++) dp[i]=0;

          for (i=1;i<=m;i++)

          {

              scanf("%d %d %d",&v[i],&p[i],&q[i]);

              v[i]/=10,p[i]*=v[i];

          }

          for (i=1;i<=m;i++)

          {

              if (q[i]==0)

              {

                          

                 for (k=0,j=1;j<=m;j++)

                 {

                     if (q[j]==i)

                     {

                         a[++k]=j;      

                     }

                 }

                 if (k==0)

                 {

                    for (y=n;y>=v[i];y--) dp[y]=dp[y-v[i]]+p[i]>dp[y]?dp[y-v[i]]+p[i]:dp[y];  

                 }

                 else if (k==1)

                 {

                      for (y=n;y>=v[i];y--)

                      {

                          max=dp[y];

                          max=dp[y-v[i]]+p[i]>max? dp[y-v[i]]+p[i]:max;

                          if(y-v[i]-v[a[1]]>=0) max=dp[y-v[i]-v[a[1]]]+p[i]+p[a[1]]>max?dp[y-v[i]-v[a[1]]]+p[i]+p[a[1]]:max;

                          dp[y]=max;

                      }

                 }

                 else if(k==2)

                 {

                      for (y=n;y>=v[i];y--)

                      {

                          max=dp[y];

                          max=dp[y-v[i]]+p[i]>max?dp[y-v[i]]+p[i]:max;

                          if(y-v[i]-v[a[1]]>=0) max=dp[y-v[i]-v[a[1]]]+p[i]+p[a[1]]>max?dp[y-v[i]-v[a[1]]]+p[i]+p[a[1]]:max;

                          if(y-v[i]-v[a[2]]>=0) max=dp[y-v[i]-v[a[2]]]+p[i]+p[a[2]]>max?dp[y-v[i]-v[a[2]]]+p[i]+p[a[2]]:max;

                          if(y-v[i]-v[a[1]]-v[a[2]]>=0) max=dp[y-v[i]-v[a[1]]-v[a[2]]]+p[i]+p[a[1]]+p[a[2]]>max?dp[y-v[i]-v[a[1]]-v[a[2]]]+p[i]+p[a[1]]+p[a[2]]:max;                  

                          dp[y]=max;

                      }

                 }  

              }   

          }    

          printf("%d\n",10*dp[n]);

    }

    return 0;

}

 

 

Hdu3449

#include<stdio.h>

using namespace std;

int n,w,i,j,k,m,p,c,v;

int dp[100001],f[100001];

int main()

{

    while(scanf("%d%d",&n,&w)!=EOF)

    {

       for(i=0;i<=w;i++) dp[i]=0;

       for(i=1;i<=n;i++)

       {

          scanf("%d%d",&p,&m);

          for(j=w;j>=p;j--) f[j]=dp[j-p]; //继承上一层的结果

          while(j>=0) f[j--]=-1; 

          for(j=1;j<=m;j++)

          {

             scanf("%d%d",&c,&v);   

             for(k=w;k>=c;k--)

             if(f[k-c]!=-1)

             f[k]=f[k-c]+v>f[k]?f[k-c]+v:f[k];//01背包部分

          }

          for(j=w;j>=0;j--)  //如果能更新上一层的状态,就更新。

             dp[j]=f[j]>dp[j]?f[j]:dp[j];   

       }

       printf("%d\n",dp[w]);                  

    }

    return 0;

}

 

 

 

 

米勒罗宾算法

 

 

 

POLLARD启发式搜索

 

计算几何

三角形内切圆半径:r=2*s/(a+b+c)

三角形外接圆半径为R=(a*b*c)/(s*4);

s是三角形面积 a,b,c是三角形三边。S=√[p(p-a)(p-b)(p-c)]=1/2*a*b*sinC

原创粉丝点击