zoukankan      html  css  js  c++  java
  • UVA 12105 Bigger is Better

    Big is Better

    题目大意:用火柴拼数字,每个数字需要的火柴如下图,共有n(n<=100)个火柴,要求拼出的数能整除m(m<=3000),求所能拼出的最大的数字是多少。

    360反馈意见截图16550429607465

    思路:按位进行DP,dp[i][j]表示用i位数表示出除以m余j的数最少需要多少根火柴棒,如果不存在则为inf,最后得到最大的i满足dp[i][0]存在,则最大位数为i,令high=i

    然后从第high位开始枚举,先从9开始,如果填9可以,等价于dp[high-1][(m-9xxxxx)%m]+f[9]<=n,相当于这一位先用掉了f[9]=6根火柴,再用剩下的火柴一定能够摆出剩下的数字才可以,否则就不行。一直往下枚举。

    代码如下:

    //https://cn.vjudge.net/problem/UVA-12105
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define N 3003
    const int inf=0xfffffff;
    using namespace std; 
    int f[]={6,2,5,5,4,5,6,3,7,6};
    int dp[202][N],n,m,ans,sum,mi[202],dig[202];
    
    void init(){
    	mi[0]=1;
    	for(int i=0;i<202;i++){
    		for(int j=0;j<=m;j++){
    			dp[i][j]=inf;
    		}
    		if(i){
    			mi[i]=(10*mi[i-1])%m;
    		}
    	}
    	
    }
    int cal(int a,int b){
    	return (a*mi[b])%m;
    }
    int cal2(int x)
    {
    	int ans=0;
    	while(x){
    		ans+=f[x%10];
    		x/=10;
    	}
    	return ans;
    }
    //#define GLQ 1
    int main()
    {
    	#ifdef GLQ  
        freopen("input.txt","r",stdin);  
        freopen("out2.txt","w",stdout);  
    	#endif // GLQ 
    	int T=0;
    	while(scanf("%d",&n),n){
    		printf("Case %d: ",++T);
    		int high=0;
    		scanf("%d",&m);
    		init();
    		for(int i=0;i<10;i++){
    			dp[0][0]=0;
    			dp[1][i%m]=min(dp[1][i%m],f[i]);
    			if(dp[1][i%m]>n) dp[1][i%m]=inf;
    		}
    		for(int i=1;;i++){
    			bool flag=0;
    			for(int j=0;j<m;j++){
    				for(int x=0;x<10;x++){
    					dp[i+1][(j+cal(x,i))%m]=min(dp[i+1][(j+cal(x,i))%m],dp[i][j]+f[x]);
    					if(dp[i+1][(j+cal(x,i))%m]>n) dp[i+1][(j+cal(x,i))%m]=inf;
    					else flag=1;
    					
    				}
    			}
    			if(dp[i][0]!=inf) high=i;
    			if(!flag) {
    				break;
    			}
    		}
    		int cnt=0;
    		int tmpn=n;
    		int tmpm=m ;
    		if(!high){
    			printf("-1
    ");
    			continue;
    		}
    		for(int i=high;i>0;i--){
    			for(int j=9;j>=0;j--){
    				if(dp[i-1][(tmpm-cal(j,i-1)+m)%m]+f[j]<=tmpn){//n和m需要修改 
    					tmpn-=f[j];
    					dig[cnt]=j;
    					tmpm=(tmpm-cal(j,i-1)+m)%m;
    					cnt++;
    	
    					break;
    				}
    			}
    
    		}
    
    		for(int i=0;i<high;i++){
    			printf("%d",dig[i]);
    		}
    		printf("
    ");
    		
    	}
    	return 0;
    }
    
  • 相关阅读:
    Canvas
    Web API 接口-JavaScript全部api接口文档
    编程中的命名设计那点事
    线程池的使用
    SRW锁的使用
    内存屏障
    VC用Beep整几首歌听听~~~
    简单的多线程并发同步演示(4种同步方法)
    C语言生成程序问题
    文件操作(输出倒数第二行、逆序输出)
  • 原文地址:https://www.cnblogs.com/Crazycatmiao/p/6910195.html
Copyright © 2011-2022 走看看