poj 1742 Coins

题目大意:

一个人有若干不同面值、同面值不同数量的硬币。告诉你硬币面值的种类和对应的数量,求用这些硬币能正好凑成多少个小于m的整数。

解题思路:

类似于素数打表,开一个m大的bool数组记录哪些数能被凑出来,外层for循环硬币的种类,对于每种硬币都把m挨个算一遍,时间复杂度为O(n*m=1000w)。在算的时候首先要判断当前的点有没有已经能被凑出来了,如果值得去凑,那么再看j-A[i]那个点是不是已经是1了,如果已经是1了,还要判断之前那个是1的点用了几次当前种类的硬币,要保证当前面值的硬币还没用完,如果条件都满足,那么就可以把当前的点更新了。

感想:

我一开始就想这么做,公式都推出来了,但是脑子短路以为这是个n*m*c=100亿的算法(我sb的想成了对于每个n的每个m点都要把已经置1的点往后挨个+c[i]来更新,忘了可以直接倒着来,如果当前的还没更新再去更新,就是这一个细节啊,看了一眼别人的博客,发现真有这么写的,以为是数据太水过了,仔细看看才发现是自己sb了)。


Sample Input

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int INF=0x7fffffff;
const int MAX_N=100005;

int n,m;
int A[105];
int C[105];
bool vis[MAX_N];
int num_of_used[MAX_N];

int main(){
    while(scanf("%d%d",&n,&m)&&n!=0){
        for(int i=1;i<=n;i++){
            scanf("%d",&A[i]);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&C[i]);
        }

        memset(vis,0,sizeof(vis));
        vis[0]=1;
        int ans=0;
        for(int i=1;i<=n;i++){
            memset(num_of_used,0,sizeof(num_of_used));
            for(int j=A[i];j<=m;j++){
                if(!vis[j]&&vis[j-A[i]]&&num_of_used[j-A[i]]<C[i]){
                    vis[j]=1;
                    num_of_used[j]=num_of_used[j-A[i]]+1;
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值