zoukankan      html  css  js  c++  java
  • [洛谷P1021][题解]邮票面值设计

    我才不是题目呢~

    0.序

    偶然被老师强迫刷到了这样一道题,正好亿年没写题解了,来此练练手+摸鱼

    1.概述

    基本思路:DFS暴力枚举+DP验证。
    先DFS出来一个序列,然后DP出所有面值用到的最少邮票数。
    (f[i])为凑出(i)面值用到的最少邮票张数。
    方程是我们在幼儿园就接触过的(f[i]=min(f[i],f[i-a[j]]+1))
    (a)数组为临时面值数组。
    求出f数组之后就枚举到第一个大于n的就行了。
    设计一下DFS:
    void DFS(int dep,int now,int tmp)
    dep:当前枚举了多少数;
    now:当前数;
    tmp:上一个最大面值。
    然后就没了。

    2.细节

    for(rg int i=now+1;i<=tmp+1;i++){
    	a[dep]=i;
    	DFS(dep+1,i,DP(dep));	
    }
    

    下界的now+1不用说,关键是上界。
    i肯定是尽量往大里枚举,
    但如果枚举到tmp+2的话中间就会空出一个数,不符合题目要求。
    所以此处为tmp+1。(不多不少刚刚好)
    2.
    题目中没有给出最大面值为多少,所以f数组看着开吧。

    3.代码

    省去了又臭又长的缺省源。

    int n,k,a[50],f[100010],ans[50],maxs;
    inline int DP(int x){
    	memset(f,0x3f,sizeof(f));
    	f[0]=0;
    	for(rg int j=1;j<=x;j++){
    		for(rg int i=a[j];i<=a[x]*n;i++){
    			f[i]=min(f[i],f[i-a[j]]+1);
    		}
    	}
    	for(rg int i=1;i<=a[x]*n;i++){
    		if(f[i+1]>n)return i;
    	}
    	return a[x]*n;
    }
    void DFS(int dep,int now,int tmp){
    	if(dep>k){
    		if(tmp>maxs){
    			maxs=tmp;
    			for(rg int i=1;i<=k;i++){
    				ans[i]=a[i];
    			}
    		}
    		return;
    	}
    	for(rg int i=now+1;i<=tmp+1;i++){
    		a[dep]=i;
    		DFS(dep+1,i,DP(dep));	
    	}
    }
    int main(){
    	Read(n),Read(k);
    	DFS(1,0,0);
    	for(rg int i=1;i<=k;i++){
    		cout<<ans[i]<<" ";
    	}
    	cout<<endl;
    	cout<<"MAX="<<maxs<<endl;
    	return 0;
    }
    

    4.完结撒花

  • 相关阅读:
    创建一个带有Event Receiver的List Definition
    查看安全日志的方式
    SysWOW64是个什么文件夹?
    IIS Log的位置
    IIS的metabase文件的位置
    Server Error in '哪一个' Application, 值得注意哦
    记录一个在SharePoint的代码中提升运行权限的方法
    Rollup and cube
    杀死数据库连接
    VS2005最近项目和最近文件清除
  • 原文地址:https://www.cnblogs.com/juruoajh/p/13144610.html
Copyright © 2011-2022 走看看