pku 1742 Coins(DP,母函数)

经典问题。给定n种硬币,每种硬币有相应的价值,并且每种硬币有一定的数量。问用这些硬币,可以组合出多少种不同的价值总和。

 

因为只需要记录某种价值总和是否存在,所以用bool[]存储信息即可。母函数思想和DP思想写出来的代码几乎是一致的。

 

#include <iostream> using namespace std; bool DP[100005]; struct node { int A,C; }info[105]; int CMP(const void* a,const void *b) { return ((node*)a)->A*((node*)a)->C-((node*)b)->A*((node*)b)->C; } int n,m,ans,maxN,temp; void solve() { for(int i=1;i<=n;i++) { temp=maxN;//当前最大价值总和 maxN+=info[i].A*info[i].C; for(int j=temp;j>=0;j--)//从末尾往前扫描,在一些情况下可提前跳出子循环,效率提高不少 { if(DP[j]) { for(int k=1;(j+k*info[i].A<=m)&&(k<=info[i].C);k++) { if(DP[j+k*info[i].A]) break;//这一步很关键,因为j是从后往前的,所以当DP[j+k*info[i].A]为真时,即可知道DP[j+(k+1)*info[i].A]为真,所以可以提前跳出循环 DP[j+k*info[i].A]=true; ans++; } } } } } int main() { while(scanf("%d%d",&n,&m)&&(n!=0||m!=0)) { memset(DP,0,sizeof(DP)); maxN=ans=0; DP[0]=true; for(int i=1;i<=n;i++) { scanf("%d",&info[i].A); } for(int i=1;i<=n;i++) { scanf("%d",&info[i].C); } qsort(info+1,n,sizeof(info[0]),CMP);//按硬币的最大范围排个序,可以减少max_N的增长速度。 solve(); printf("%d/n",ans); } return 0; }

你可能感兴趣的:(pku 1742 Coins(DP,母函数))