swjtu oj 1579 加号问题

http://acm.swjtu.edu.cn/JudgeOnline/showproblem?problem_id=1579

明显的DP算法。方便起见,定义一个结构体answer。用来储存一个字符串数字,当然拉,也可以不用,看个人喜好。输入字符串s ,加号个数 m,一个answer的二维数组 OPT[ i ][ j ] ,表示: 用 s 的前 i 的 字符,在这i个字符中加入 j 个加号 ,所求的最小得和。

首先,OPT[ 0 ][ i ] = 0. 表示,取a中的 0个字符 ,加入i 个加号,得到的数,自然是0 .

OPT[ i ][ 0 ]=a[ 0....i-1 ] ,表示 ,取a中的前i个字符 ,加入0个加号,很明显,得到的数为

a[0..i-1].

因此,得到以下公式:

OPT[ n ][ m ] = min{

                                  OPT[ n-1 ][m-1 ] + a[ n-1...n-1 ],

                                     OPT[ n-2 ][m-1 ] + a[ n-2...n-1 ],

                                     OPT[ n-3 ][m-1 ] + a[ n-3...n-1 ],

                                   OPT[ n-4 ][m-1 ] + a[ n-4...n-1 ],

                                   ............

                                   ............

                                    OPT[   0 ][ m-1 ]+a[ 0....n-1 ];

                                   }

循环计算OPT[ n ][ m ];

n=strlen(n);

为 OPT [   i ] [ 0 ] , OPT [ 0 ] [ j ] 赋初值(i=0,1,2,...n) (j=0,1,2.....m);

For i 1 to n

For j 1 to m

计算 OPT[ i ][ j ] (按照以上公式)

输出 OPT[ n ][ m ]

算法就这么简单,但是关于实现,首先,必须写一个字符串相加的函数,由于位数的关系,所有加法都必须基于字符串,其次,一个字符串数字比较的函数,不能用strcmp.





  #include <stdio.h>
#include <string>
typedef struct {
 char s[202];
 }answer;
  answer OPT[201][21]; //OPT[i][j],??s????????i????????????j??????????????????????
char *plus(char *a , char *b,int p,int i)
 {
  char s[250],sum[250];
  int k=0;
  for(k=0;p+k<=i;k++)
  s[k]=b[p+k];
  sum[0]='0';
  int la=strlen(a);
  int length=la>k?la:k;
  int min=la<k?la:k;
  int sign=0,m;
  length+=1;
  for(m=0;m<min;m++){
   sum[length-m-1]=a[la-m-1]+s[k-m-1]+sign-'0';
   if(sum[length-m-1]>'9') {sum[length-m-1]-=10;sign=1;}
  else
     sign=0;
   } 
  while(m<la) {sum[length-m-1]=a[la-m-1]+sign;
               if(sum[length-m-1]>'9') {sum[length-m-1]-=10;sign=1;}
                else
     sign=0;m++;}
  while(m<k) {sum[length-m-1]=s[k-m-1]+sign; 
      if(sum[length-m-1]>'9') {sum[length-m-1]-=10;sign=1;}
     else
     sign=0;m++;}
  if(sum[0]=='0'&&sign==1) sum[0]='1';
  sum[length]='\0';
  if(sum[0]=='0')
  return sum+1;
  else
  return sum;
  }

void fun(char *s,int m);
 int aSmaller(char *a,char *b){
  int la,lb;
  la=strlen(a);
  lb=strlen(b);
  if(la<lb) return 1;
  else
  if(la>lb) return 0;
   else
    {
     int i;
     for(i=0;i<la;i++)
      if(a[i]<b[i]) return 1;
      else
      if(a[i]>b[i]) return 0;
 }
  return 0;
  }
 
char *plus(char *a , char *b,int p,int i);
int main()
  {
   int n;
   scanf("%d",&n);
    while(n--)
     {
      char s[201];
      int m;
   scanf("%s%d",s,&m);
 
   fun(s,m);
      }
  
   return 0;
   }
   void get(char *a,char *s,int i)
   {
    int j=0;
    for(j=0;j<i;j++)
    a[j]=s[j];
    a[j]='\0';
    }
  void fun(char *s,int m)
  { 

   int ls=strlen(s);
  
       int j,i;
  for(j=0;j<=m;j++)
   strcpy(OPT[0][j].s,"0"); 
   
   for(i=0;i<=ls;i++) 
    get(OPT[i][0].s,s,i);
   strcpy(OPT[0][0].s,"0");
   for(i=1;i<=ls;i++)
    for(j=1;j<=m;j++) 
   {
      if(j>=i) {strcpy(OPT[i][j].s,OPT[i][j-1].s);continue;}  
    char min[250]; char sum[250];
   strcpy(sum,plus(OPT[i-1][j-1].s,s,i-1,i-1));
   strcpy(min,sum);
    int p;
    for(p=i-2;p>=0;p--)
    {
    
     strcpy(sum,plus(OPT[p][j-1].s,s,p+1-1,i-1));
     if(aSmaller(sum,min))
           strcpy(min,sum);
  
   
     }
     strcpy(OPT[i][j].s,min);
   }
printf("%s\n",OPT[ls]­.s);
  
  }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值