poj1276 Cash Machine


TLE版本:
  1. #include <stdio.h>
  2. int cash;   //0<=cash<=100000
  3. int N;      //现金种类数量,0<=N<=10
  4. int d[10];  //现金面额,1<=d[i]<=1000
  5. int n[10];  //现金数量,1<=n[i]<=1000
  6. int memo[100000][10];
  7. int r[100000];
  8. int dp()
  9. {
  10.     int i, j, k, total=0, max=0;
  11.     for (i=0; i<N; i++)//计算各种面额的现金总数量
  12.         total+=n[i];
  13.     for (i=0; i<N; i++){//初始化
  14.         memo[d[i]][i]=1;
  15.         r[i]=1;
  16.         if (d[i]<=cash && d[i]>max)
  17.             max=d[i];
  18.     }
  19.     for (i=1; i<total && max<cash; i++){//i代表第i张现金
  20.         for (j=0; j<N; j++){//j代表第j种现金
  21.             for (k=0; k<max; k++){//k代表到第i张现金为止的现金总额
  22.                 if (r[k] && !r[k+d[j]]){//如果基础现金总额k存在而且k+d[j]不存在
  23.                     memo[k+d[j]][j]++;
  24.                     r[k+d[j]]=1;
  25.                     if (k+d[j]<=cash && k+d[j]>max)
  26.                         max=k+d[j];
  27.                 }
  28.             }
  29.         }
  30.     }
  31.     return max;
  32. }
  33. main(int argc, char *argv[])
  34. {
  35.     int i, j, res;
  36.     //freopen("poj1276.txt", "r", stdin);
  37.     while(scanf("%d%d", &cash, &N)!=EOF){
  38.         for (i=0; i<N; i++)
  39.             scanf("%d%d", &d[i], &n[i]);
  40.         for (i=0; i<100000; i++){
  41.             r[i]=0;
  42.             for (j=0; j<10; j++)
  43.                 memo[i][j]=0;
  44.         }
  45.         res=dp();
  46.         printf("%d/n", res);
  47.     }
  48. }
yet another tle版本:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. int cash;   //0<=cash<=100000
  5. int N;      //现金种类数量,0<=N<=10
  6. int d[10];  //现金面额,1<=d[i]<=1000
  7. int n[10];  //现金数量,1<=n[i]<=1000
  8. int memo[100000][10];
  9. int r[100000];//标记已经计算过的金额数目
  10. int f[100000];//记录已经计算过的金额数目
  11. int dp()
  12. {
  13.     int i, j, k, total=0, max=0, count=0, tmp;
  14.     for (i=0; i<N; i++)//计算各种面额的现金总数量
  15.         total+=n[i];
  16.     for (i=0; i<N; i++){//初始化
  17.         if (n[i]>0){
  18.             memo[d[i]][i]=1;
  19.             r[d[i]]=1;
  20.             count++;
  21.             f[i]=d[i];
  22.             if (d[i]<=cash && d[i]>max)
  23.                 max=d[i];
  24.         }
  25.     }
  26.     for (i=1; i<=total && max<cash; i++){//i代表第i张现金
  27.         for (j=0; j<N; j++){//j代表第j种现金
  28.             tmp=count;
  29.             for (k=0; k<count; k++){//k代表到第i张现金为止的现金总额
  30.                 if (r[f[k]] && (f[k]+d[j]<100000) && !r[f[k]+d[j]] && memo[f[k]][j]<n[j]){
  31.                     //如果基础现金总额k存在而且k+d[j]没有被计算过,并且总额所用的第j种现金数量足够
  32.                     if (f[k]+d[j]<=cash){
  33.                         memo[f[k]+d[j]][j]=memo[f[k]][j]+1;
  34.                         r[f[k]+d[j]]=1;
  35.                         f[tmp++]=f[k]+d[j];
  36.                         if (f[k]+d[j]>max)
  37.                             max=f[k]+d[j];
  38.                     }
  39.                 }
  40.             }
  41.             count=tmp;
  42.         }
  43.     }
  44.     return max;
  45. }
  46. main(int argc, char *argv[])
  47. {
  48.     int i, j, res, nn, dd;
  49.     double start, end;
  50.     //freopen("poj1276.txt", "r", stdin);
  51.     while(scanf("%d%d", &cash, &N)!=EOF){
  52.         for (i=0; i<N; i++){
  53.             scanf("%d%d", &nn, &dd);
  54.             if (nn!=0){
  55.                 n[i]=nn;
  56.                 d[i]=dd;
  57.             }
  58.             else{
  59.                 i--;
  60.                 N--;
  61.             }
  62.         }
  63.         start=clock();
  64.         for (i=0; i<cash; i++){//初始化r[]和memo[][]
  65.             r[i]=0;
  66.             for (j=0; j<10; j++)
  67.                 memo[i][j]=0;
  68.         }
  69.         res=dp();
  70.         end=clock();
  71.         printf("%d/n", res);
  72.         printf("run time %.0fms/n", end-start);
  73.     }
  74. }
用01背包的解决方案,经过无数次的WA和RE(一些小细节方面),终于AC了!泪奔
Memory:648K  Time:63MS
以下是AC版本,以后再进行优化。
  1. #include <stdio.h>
  2. #include <math.h>
  3. #define max(a,b) ((a)>(b)) ? (a) : (b)
  4. int weight[10001];//货币价值
  5. int amount[10001];//货币种类数量
  6. int f[100001];
  7. int Pack(int n, int v)//01背包问题
  8. {
  9.     int i, j;
  10.     for (j=0; j<=v; j++)
  11.         f[j]=0;
  12.     for (i=1; i<=n; i++){
  13.         if (amount[i]!=0){
  14.             for (j=v; j>=weight[i]; j--)
  15.                 f[j]=max(f[j-weight[i]]+weight[i], f[j]);
  16.         }
  17.     }
  18.     return f[v];
  19. }
  20. void Divide(int *n, int v)//将数量为amount的货币1,2,4,...,2^(k-1),n[i]-2^k+1,
  21. {                         //(k是满足n[i]-2^k+1>0的最大整数)的相同价值的货币
  22.     int i, k, t;
  23.     t=*n;
  24.     for (i=1; i<=t; i++){
  25.         k=1;
  26.         while (amount[i]-pow(2.0, k+1)+1>0 && weight[i]*(int)pow(2.0, k+1)<=v){
  27.             weight[++(*n)]=weight[i]*(int)pow(2.0, k++);
  28.             amount[*n]=1;
  29.         }
  30.         if (amount[i]-(int)pow(2.0, k)+1 > 0){
  31.             weight[++(*n)]=weight[i]*(amount[i]-(int)pow(2.0, k)+1);
  32.             amount[*n]=1;
  33.         }
  34.     }
  35. }
  36. main(int argc, char *argv[])
  37. {
  38.     int n, v, i, res;
  39.     //freopen("poj1276.txt", "r", stdin);
  40.     while(scanf("%d%d", &v, &n)!=EOF){
  41.         for (i=1; i<=n; i++)
  42.             scanf("%d%d", &amount[i], &weight[i]);
  43.         Divide(&n, v);
  44.         res=Pack(n, v);
  45.         printf("%d/n", res);
  46.     }
  47. }

参考链接: http://duanple.blog.163.com/blog/static/709717672008101985128651/;
               http://bbs.113314.cn/thread-76-1-1.html.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值