POJ3181 完全背包+高精度数模板

27 篇文章 0 订阅
22 篇文章 0 订阅

题意

  • 有1~k,这k个数,每种数可以用任意多次,问你组成n的方案数
  • N<=1000,k<=100

思路

  • 就是完全背包,把k种物品,第i种重量为i,重量限制为N的方案数,只要把原本的max改为sum即可
  • 由于k,n比较小,我就没优化的写了一个,将将过。。之后重写了一个优化后的,就都贴出来了
  • 注意要用高精度数

实现

没优化的

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;

const int MAXSIZE = 50;

struct BigInt{
public:
    int a[MAXSIZE];
    int length;
public:
    BigInt():length(0){memset(a,0,sizeof(a));}
    BigInt(string s);
    BigInt(int b);
    BigInt(const BigInt& c);
    BigInt operator=(int b);
    BigInt operator=(string s); 
};
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////

BigInt::BigInt(string s)
{
    memset(a,0,sizeof(a));
    *this = s;
}
BigInt::BigInt(int b)
{
    memset(a,0,sizeof(a));
    *this = b;
}
BigInt::BigInt(const BigInt& c)
{
    int i;
    memset(a,0,sizeof(a));  
    length = c.length;
    memset(a,0,sizeof(a));
    for(i=0;i<length;i++)
    {
        a[i] = c.a[i];
    }
}


BigInt BigInt::operator=(int b)
{
    memset(a,0,sizeof(a));
    if(b==0)
    {
        a[0] = 0;
        length = 1;
        return *this;
    }
    if(b<0)
    {
        b = -b;
    }
    for(length=0;b>0;length++)
    {
        a[length] = b%10;
        b /= 10;
    }
    return *this;
}

BigInt BigInt::operator=(string s)
{
    int i;
    length = s.length();
    memset(a,0,sizeof(a));
    for(i=0;i<length;i++)
    {
        a[length-i-1] = (int)(s[i] - '0');
    }
    return *this;
}


BigInt operator+(const BigInt& d,const BigInt& b)
{
    int i;
    int jinWei = 0;
    BigInt sum;
    int max_length = (d.length<b.length)?b.length:d.length;
    for(i=0;i<max_length;i++)
    {
        jinWei = d.a[i]+b.a[i]+jinWei;
        sum.a[i] = jinWei%10;
        jinWei/=10;
    }
    sum.length = i;                //sum.length 易忘赋值 
    if(jinWei!=0) 
    {
        sum.a[i] = jinWei; //加上最高位进位
        sum.length++; 
    }
    return sum;
}
BigInt operator-(const BigInt& d,const BigInt& b)   //适宜d>b时 
{
    int i,j;
    int tuiWei = 0;
    BigInt sum;
    int max_length = (d.length<b.length)?b.length:d.length;
    for(i=0;i<max_length;i++)
    {
        tuiWei = d.a[i]-b.a[i]-tuiWei;
        if(tuiWei>=0)
        {
            sum.a[i] = tuiWei;
            tuiWei = 0;
        }
        else
        {
            sum.a[i] = 10+tuiWei;
            tuiWei = 1;
        }
    }
    sum.length = i;                //sum.length 易忘赋值
    for(j=i-1;sum.a[j]==0&&j>0;j--)
        sum.length--;
    return sum;
}

BigInt operator*(const BigInt& d,const BigInt& b)
{
    int i,j,k;
    int jinWei=0;
    BigInt temp = 0;
    BigInt fuck = 0;
    if(b.a[0]==0&&b.length == 1||d.a[0]==0&&d.length == 1)
    {
        return b;
    }
    for(i=0;i<b.length;i++)   //b作为乘数 
    {
        jinWei = 0;
        temp = 0; 
        for(j=0;j<d.length;j++) //a*b[i] 
        {
            jinWei = d.a[j]*b.a[i] + jinWei;
            temp.a[j] = jinWei%10;
            jinWei /= 10;
        }
        temp.length = j;
        if(jinWei!=0)
        {
            temp.a[j] = jinWei; 
            temp.length++;
        }
        if(i!=0)
        {
            for(k=temp.length-1;k>=0;k--)  //左移i位 
            {
                temp.a[k+i] = temp.a[k];
                temp.a[k] = 0;
            }
            temp.length += i;
        }
        fuck = fuck+temp;
    }
    return fuck;
}
bool operator<(const BigInt& d,const BigInt& b)
{
    if(d.length<b.length)
        return true;
    if(d.length>b.length)
        return false;
    for(int i=b.length-1;i>=0;i--)
    {
        if(d.a[i]>b.a[i])
            return false;
        if(d.a[i]<b.a[i])
            return true;
    }
    return false;
}
bool operator==(const BigInt& d,const BigInt& b)
{
    if(d.length!=b.length)
        return false;
    for(int i=b.length-1;i>=0;i--)
    {
        if(d.a[i]!=b.a[i])
            return true;
    }
    return true;
}
bool operator!=(const BigInt& d,const BigInt& b)
{
    return !(d==b);
}
bool operator>(const BigInt& d,const BigInt& b)
{
    return !(d==b||d<b);
}
bool operator<=(const BigInt& d,const BigInt& b)
{
    return !(d>b);
}
bool operator>=(const BigInt& d,const BigInt& b)
{
    return !(d<b);
}

/////////////////////////////////////////////
/////////////////////////////////////////////
char* toString(BigInt a)
{
    int i;
    //注意static
    static char s[MAXSIZE];
    for(i=a.length-1;i>=0;i--)
    {
        s[a.length-i-1] = (char)(a.a[i]+'0');
    }
    s[a.length] =  '\0';
    return s;
}


int n,k;
BigInt dp[2][1005];
int main(){
    cin>>n>>k;

    dp[0][0] = BigInt(1);
    for (int i=1;i<=k;i++){
        for (int j=0;j<=n;j++){
            dp[i&1][j] = BigInt(0);
            for (int k=0;k*i <= j;k++){
                dp[i&1][j] = dp[i&1][j] + dp[(i-1)&1][j-k*i];
            }
        }
    }
    cout <<toString(dp[k&1][n] )<<'\n';

    return 0;
}

优化后的

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;

const int MAXSIZE = 50;

struct BigInt{
public:
    int a[MAXSIZE];
    int length;
public:
    BigInt():length(0){memset(a,0,sizeof(a));}
    BigInt(string s);
    BigInt(int b);
    BigInt(const BigInt& c);
    BigInt operator=(int b);
    BigInt operator=(string s); 
};
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////

BigInt::BigInt(string s)
{
    memset(a,0,sizeof(a));
    *this = s;
}
BigInt::BigInt(int b)
{
    memset(a,0,sizeof(a));
    *this = b;
}
BigInt::BigInt(const BigInt& c)
{
    int i;
    memset(a,0,sizeof(a));  
    length = c.length;
    memset(a,0,sizeof(a));
    for(i=0;i<length;i++)
    {
        a[i] = c.a[i];
    }
}


BigInt BigInt::operator=(int b)
{
    memset(a,0,sizeof(a));
    if(b==0)
    {
        a[0] = 0;
        length = 1;
        return *this;
    }
    if(b<0)
    {
        b = -b;
    }
    for(length=0;b>0;length++)
    {
        a[length] = b%10;
        b /= 10;
    }
    return *this;
}

BigInt BigInt::operator=(string s)
{
    int i;
    length = s.length();
    memset(a,0,sizeof(a));
    for(i=0;i<length;i++)
    {
        a[length-i-1] = (int)(s[i] - '0');
    }
    return *this;
}


BigInt operator+(const BigInt& d,const BigInt& b)
{
    int i;
    int jinWei = 0;
    BigInt sum;
    int max_length = (d.length<b.length)?b.length:d.length;
    for(i=0;i<max_length;i++)
    {
        jinWei = d.a[i]+b.a[i]+jinWei;
        sum.a[i] = jinWei%10;
        jinWei/=10;
    }
    sum.length = i;                //sum.length 易忘赋值 
    if(jinWei!=0) 
    {
        sum.a[i] = jinWei; //加上最高位进位
        sum.length++; 
    }
    return sum;
}
BigInt operator-(const BigInt& d,const BigInt& b)   //适宜d>b时 
{
    int i,j;
    int tuiWei = 0;
    BigInt sum;
    int max_length = (d.length<b.length)?b.length:d.length;
    for(i=0;i<max_length;i++)
    {
        tuiWei = d.a[i]-b.a[i]-tuiWei;
        if(tuiWei>=0)
        {
            sum.a[i] = tuiWei;
            tuiWei = 0;
        }
        else
        {
            sum.a[i] = 10+tuiWei;
            tuiWei = 1;
        }
    }
    sum.length = i;                //sum.length 易忘赋值
    for(j=i-1;sum.a[j]==0&&j>0;j--)
        sum.length--;
    return sum;
}

BigInt operator*(const BigInt& d,const BigInt& b)
{
    int i,j,k;
    int jinWei=0;
    BigInt temp = 0;
    BigInt fuck = 0;
    if(b.a[0]==0&&b.length == 1||d.a[0]==0&&d.length == 1)
    {
        return b;
    }
    for(i=0;i<b.length;i++)   //b作为乘数 
    {
        jinWei = 0;
        temp = 0; 
        for(j=0;j<d.length;j++) //a*b[i] 
        {
            jinWei = d.a[j]*b.a[i] + jinWei;
            temp.a[j] = jinWei%10;
            jinWei /= 10;
        }
        temp.length = j;
        if(jinWei!=0)
        {
            temp.a[j] = jinWei; 
            temp.length++;
        }
        if(i!=0)
        {
            for(k=temp.length-1;k>=0;k--)  //左移i位 
            {
                temp.a[k+i] = temp.a[k];
                temp.a[k] = 0;
            }
            temp.length += i;
        }
        fuck = fuck+temp;
    }
    return fuck;
}
bool operator<(const BigInt& d,const BigInt& b)
{
    if(d.length<b.length)
        return true;
    if(d.length>b.length)
        return false;
    for(int i=b.length-1;i>=0;i--)
    {
        if(d.a[i]>b.a[i])
            return false;
        if(d.a[i]<b.a[i])
            return true;
    }
    return false;
}
bool operator==(const BigInt& d,const BigInt& b)
{
    if(d.length!=b.length)
        return false;
    for(int i=b.length-1;i>=0;i--)
    {
        if(d.a[i]!=b.a[i])
            return true;
    }
    return true;
}
bool operator!=(const BigInt& d,const BigInt& b)
{
    return !(d==b);
}
bool operator>(const BigInt& d,const BigInt& b)
{
    return !(d==b||d<b);
}
bool operator<=(const BigInt& d,const BigInt& b)
{
    return !(d>b);
}
bool operator>=(const BigInt& d,const BigInt& b)
{
    return !(d<b);
}

/////////////////////////////////////////////
/////////////////////////////////////////////
char* toString(BigInt a)
{
    int i;
    //注意static
    static char s[MAXSIZE];
    for(i=a.length-1;i>=0;i--)
    {
        s[a.length-i-1] = (char)(a.a[i]+'0');
    }
    s[a.length] =  '\0';
    return s;
}


int n,k;
BigInt dp[1005]; 
int main(){
    cin>>n>>k;

    dp[0] = BigInt(1);
    for (int i=1;i<=k;i++){
        for (int j=0;j<=n;j++){
            if (j >= i)
                dp[j] = dp[j-i] + dp[j];
        }
    }
    cout <<toString(dp[n] )<<'\n';

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值