124. [NOI1996]添加号
★☆ 输入文件:exam4.in
输出文件:
exam4.out
简单对比
时间限制:2 s 内存限制:128 MB
【问题描述】
有一个由数字 1 , 2 , ... , 9 组成的数字串(长度不超过 200 ),问如何将 M(M<=20) 个加号 ("+") 插入到这个数字串中,使所形成的算术表达式的值最小。请编一个程序解决这个问题。 注意: 加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的加号相邻。 M 保证小于数字串的长度。 例如:数字串 79846 ,若需要加入两个加号,则最佳方案为 79+8+46 ,算术表达式的值 133 。
【输入格式】
数字串在输入文件的第一行行首(数字串中间无空格且不折行),M的值在输入文件的第二行行首。
【输出格式】
输出所求得的最小和的精确值。
【输入输出样例】
输入:
exam4.in
82363983742
3
输出:
exam4.out
2170
高精度+dp
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 999999999999LL
#define MAX_N 250
typedef long long ll;
char text[MAX_N];
int k;
class BigInt
{
public:
int dat[MAX_N];
int len;
public:
BigInt()
{
dat[0]=0;
len=1;
}
BigInt(const char *str)
{
int len=strlen(str);
for(int i=0;i<len;i++)
{
dat[i]=str[len-i-1]-'0';
}
this->len=len;
}
BigInt operator = (const BigInt &b)
{
memcpy(dat,b.dat,sizeof(dat));
len=b.len;
return b;
}
void Print()
{
for(int i=len-1;i>=0;i--)
{
cout<<dat[i];
}
cout<<endl;
}
};
BigInt operator + (const BigInt &a,const BigInt &b)
{
BigInt c("0");
int len=max(a.len,b.len);
memset(c.dat,0,sizeof(c.dat));
for(int i=0;i<len;i++)
{
if(i<a.len)
c.dat[i]+=a.dat[i];
if(i<b.len)
c.dat[i]+=b.dat[i];
}
for(int i=0;i<len;i++)
{
c.dat[i+1]+=c.dat[i]/10;
c.dat[i]%=10;
}
if(c.dat[len]) c.len=len+1;
else c.len=len;
return c;
}
bool operator < (const BigInt &a,const BigInt &b)
{
if(a.len!=b.len)
{
return a.len<b.len;
}
for(int i=a.len-1;i>=0;i--)
{
if(a.dat[i]!=b.dat[i])
return a.dat[i]<b.dat[i];
}
return false;
}
BigInt d[MAX_N][MAX_N];
bool bd[MAX_N][MAX_N];
char tt[MAX_N];
BigInt GetNum(int s,int t)
{
int len=0;
for(int i=0;i<=t-s;i++)
{
tt[len++]=text[i+s];
}
tt[len]=0;
return BigInt(tt);
}
BigInt dp(int t,int k)
{
BigInt minx("0");
minx.len=205;
if(bd[t][k]) return d[t][k];
if(k==0)
{
bd[t][k]=true;
return d[t][0]=GetNum(0,t);
}
if(k>=t+1)
{
bd[t][k]=true;
return d[t][k]=minx;
}
for(int i=0;i<t;i++)
{
BigInt num=GetNum(i+1,t)+dp(i,k-1);
if(num<minx)
{
minx=num;
}
}
bd[t][k]=true;
return d[t][k]=minx;
}
int main()
{
freopen("exam4.in","r",stdin);
freopen("exam4.out","w",stdout);
cin>>text;
cin>>k;
BigInt bint=dp(strlen(text)-1,k);
//BigInt bint("6666");
// bint=bint+bint;
bint.Print();
return 0;
}