TLE版本:
- #include <stdio.h>
- int cash; //0<=cash<=100000
- int N; //现金种类数量,0<=N<=10
- int d[10]; //现金面额,1<=d[i]<=1000
- int n[10]; //现金数量,1<=n[i]<=1000
- int memo[100000][10];
- int r[100000];
- int dp()
- {
- int i, j, k, total=0, max=0;
- for (i=0; i<N; i++)//计算各种面额的现金总数量
- total+=n[i];
- for (i=0; i<N; i++){//初始化
- memo[d[i]][i]=1;
- r[i]=1;
- if (d[i]<=cash && d[i]>max)
- max=d[i];
- }
- for (i=1; i<total && max<cash; i++){//i代表第i张现金
- for (j=0; j<N; j++){//j代表第j种现金
- for (k=0; k<max; k++){//k代表到第i张现金为止的现金总额
- if (r[k] && !r[k+d[j]]){//如果基础现金总额k存在而且k+d[j]不存在
- memo[k+d[j]][j]++;
- r[k+d[j]]=1;
- if (k+d[j]<=cash && k+d[j]>max)
- max=k+d[j];
- }
- }
- }
- }
- return max;
- }
- main(int argc, char *argv[])
- {
- int i, j, res;
- //freopen("poj1276.txt", "r", stdin);
- while(scanf("%d%d", &cash, &N)!=EOF){
- for (i=0; i<N; i++)
- scanf("%d%d", &d[i], &n[i]);
- for (i=0; i<100000; i++){
- r[i]=0;
- for (j=0; j<10; j++)
- memo[i][j]=0;
- }
- res=dp();
- printf("%d/n", res);
- }
- }
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- int cash; //0<=cash<=100000
- int N; //现金种类数量,0<=N<=10
- int d[10]; //现金面额,1<=d[i]<=1000
- int n[10]; //现金数量,1<=n[i]<=1000
- int memo[100000][10];
- int r[100000];//标记已经计算过的金额数目
- int f[100000];//记录已经计算过的金额数目
- int dp()
- {
- int i, j, k, total=0, max=0, count=0, tmp;
- for (i=0; i<N; i++)//计算各种面额的现金总数量
- total+=n[i];
- for (i=0; i<N; i++){//初始化
- if (n[i]>0){
- memo[d[i]][i]=1;
- r[d[i]]=1;
- count++;
- f[i]=d[i];
- if (d[i]<=cash && d[i]>max)
- max=d[i];
- }
- }
- for (i=1; i<=total && max<cash; i++){//i代表第i张现金
- for (j=0; j<N; j++){//j代表第j种现金
- tmp=count;
- for (k=0; k<count; k++){//k代表到第i张现金为止的现金总额
- if (r[f[k]] && (f[k]+d[j]<100000) && !r[f[k]+d[j]] && memo[f[k]][j]<n[j]){
- //如果基础现金总额k存在而且k+d[j]没有被计算过,并且总额所用的第j种现金数量足够
- if (f[k]+d[j]<=cash){
- memo[f[k]+d[j]][j]=memo[f[k]][j]+1;
- r[f[k]+d[j]]=1;
- f[tmp++]=f[k]+d[j];
- if (f[k]+d[j]>max)
- max=f[k]+d[j];
- }
- }
- }
- count=tmp;
- }
- }
- return max;
- }
- main(int argc, char *argv[])
- {
- int i, j, res, nn, dd;
- double start, end;
- //freopen("poj1276.txt", "r", stdin);
- while(scanf("%d%d", &cash, &N)!=EOF){
- for (i=0; i<N; i++){
- scanf("%d%d", &nn, &dd);
- if (nn!=0){
- n[i]=nn;
- d[i]=dd;
- }
- else{
- i--;
- N--;
- }
- }
- start=clock();
- for (i=0; i<cash; i++){//初始化r[]和memo[][]
- r[i]=0;
- for (j=0; j<10; j++)
- memo[i][j]=0;
- }
- res=dp();
- end=clock();
- printf("%d/n", res);
- printf("run time %.0fms/n", end-start);
- }
- }
Memory:648K Time:63MS
以下是AC版本,以后再进行优化。
- #include <stdio.h>
- #include <math.h>
- #define max(a,b) ((a)>(b)) ? (a) : (b)
- int weight[10001];//货币价值
- int amount[10001];//货币种类数量
- int f[100001];
- int Pack(int n, int v)//01背包问题
- {
- int i, j;
- for (j=0; j<=v; j++)
- f[j]=0;
- for (i=1; i<=n; i++){
- if (amount[i]!=0){
- for (j=v; j>=weight[i]; j--)
- f[j]=max(f[j-weight[i]]+weight[i], f[j]);
- }
- }
- return f[v];
- }
- void Divide(int *n, int v)//将数量为amount的货币1,2,4,...,2^(k-1),n[i]-2^k+1,
- { //(k是满足n[i]-2^k+1>0的最大整数)的相同价值的货币
- int i, k, t;
- t=*n;
- for (i=1; i<=t; i++){
- k=1;
- while (amount[i]-pow(2.0, k+1)+1>0 && weight[i]*(int)pow(2.0, k+1)<=v){
- weight[++(*n)]=weight[i]*(int)pow(2.0, k++);
- amount[*n]=1;
- }
- if (amount[i]-(int)pow(2.0, k)+1 > 0){
- weight[++(*n)]=weight[i]*(amount[i]-(int)pow(2.0, k)+1);
- amount[*n]=1;
- }
- }
- }
- main(int argc, char *argv[])
- {
- int n, v, i, res;
- //freopen("poj1276.txt", "r", stdin);
- while(scanf("%d%d", &v, &n)!=EOF){
- for (i=1; i<=n; i++)
- scanf("%d%d", &amount[i], &weight[i]);
- Divide(&n, v);
- res=Pack(n, v);
- printf("%d/n", res);
- }
- }
参考链接: http://duanple.blog.163.com/blog/static/709717672008101985128651/;
http://bbs.113314.cn/thread-76-1-1.html.