zoukankan      html  css  js  c++  java
  • poj1742 coins

    题目链接:https://vjudge.net/problem/POJ-1742

    有点奇特的dp。做题思路来自于挑战程序设计的多重部分和那一节。一开始过了hdu2844但是poj1742过不去,今天终于过了...

    n<=100,m<=100000直接用多重背包肯定tle,所以要有一些好的状态设计。

    设f[i][j]表示用到第i种面值,组成面值j,第i种还剩多少个。f[i][j]=-1表示不能组成j。那么

    1. 若f[i-1][j]>=0则f[i][j]=c[i],因为前i-1种面值可以组成j,第i种自然剩下c[i]个

    2. f[i-1][j]<0

    1) 若j<a[i],f[i][j]=-1。因为前i-1种不能组成j,加上>j的a[i]肯定也不能组成j

    2)若j>=a[i]   

      ① 若f[i][j-a[i]]>0,即可以组成j-a[i]还有剩余,则f[i][j]=f[i][j-a[i]]-1

      ② f[i][j-a[i]]<=0 则f[i][j]=-1。

    至此就讨论完了。注意一个坑点:这题空间只有30000kb,数组只能开成一维的。还纠结过开成一维j要不要倒着循环,想了想是不对的,因为那样每个i种面值相当于只用了一次

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int maxn=100+10;
    const int maxm=100000+10;
    int a[maxn],c[maxn],f[maxm];
    int n,m,i,j,k,ans;
    
    int main(){
    	//freopen("poj1742.txt","r",stdin);
    	scanf("%d%d",&n,&m);
    	while (n!=0&&m!=0){
    	  for (i=1;i<=n;i++) scanf("%d",&a[i]);
    	  for (i=1;i<=n;i++) scanf("%d",&c[i]);
    	  memset(f,-1,sizeof(f));
    	  f[0]=0;
    	  for (i=1;i<=n;i++)
    	    for (j=0;j<=m;j++){
    	  	  if (f[j]>=0) f[j]=c[i];
    	  	  else{
    	  		if (j<a[i]) f[j]=-1;
    	  		if (j>=a[i]){
    	  			if (f[j-a[i]]>0) f[j]=f[j-a[i]]-1;
    	  			else f[j]=-1;
    			  }
    		  }
    	    }
    	  ans=0;
    	  for (i=1;i<=m;i++) if (f[i]>=0) ans++;
    	  printf("%d
    ",ans);
    	  scanf("%d%d",&n,&m);
        }
        //fclose(stdin);
    	return 0;
    }
    

      

     

  • 相关阅读:
    Linux防火墙配置(iptables, firewalld)
    利用RMAN恢复整个数据库
    RMAN常用命令汇总!
    Oracle RMAN 恢复数据库到不同主机(二)
    Oracle RMAN 恢复数据库到不同主机(一)
    linux sar命令详解
    Linux定时任务Crontab命令详解
    Win7 U盘安装Ubuntu16.04 双系统详细教程
    linux定时任务crontab
    linux服务器端口netstat
  • 原文地址:https://www.cnblogs.com/edmunds/p/12442642.html
Copyright © 2011-2022 走看看