zoukankan      html  css  js  c++  java
  • 天平 数学+DP

    【问题描述】
    大牛最近正在为自己的体重而苦恼,他想称量自己的体重。于是,他找来一个天平与许
    多砝码。
    砝码的重量均是 n 的幂次,n^1、n^2、n^3、n^4、n^5 的......大牛想知道至少要多少个
    砝码才可以称出他的重量 m。注意砝码可以放左边,也可以放右边。
    【输入格式】
    第一行一个正整数 m,表示大牛的重量;
    第二行一个正整数 n,表示砝码重量幂次的底;
    【输出格式】
    一个整数表示最少所需的砝码数。
    【样例输入】
    99
    10
    【样例输出】
    2
    【数据范围】
    对于 30%的数据点,m <= 2^63 - 1
    对于 100%的数据点,0 <= m <= 10^10000, 0 < n <= 10000


    首先我们很容易想到把m化成n进制数来考虑。

    所以我们先用高进度除法把m化成n进制数,然后因为可以放左右边,所以到了当前位,我们可以选择放x个砝码,也可以选择放n-x个砝码,然后下一位加1。

    考虑到当前选择没有后效性,我们于是考虑在每一位上DP。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    #define ll long long
    #define il inline
    #define db double
    
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    
    using namespace std;
    
    int n;
    
    char mm[100045];
    
    int a[100045],b[100045];
    
    int yushu[100045],yu;
    
    int len;
    
    bool flag;
    
    il void get()
    {
    	int rest=a[0];
    	int now=1;
    	int cnt=0;
    	while(now<=len-1)
    		{
    			rest=rest*10+a[now];
    			if(rest>=n)
    				{
    					b[cnt++]=rest/n;
    					rest=rest%n;
    				}
    			else b[cnt++]=0;
    			now++;
    		}
    
    	yushu[++yu]=rest;
    
    	for(int i=0;i<cnt/2;i++)
    		swap(b[i],b[cnt-i-1]);
    
    	while(b[cnt-1]==0)
    		cnt--;
    
    	for(int i=0;i<cnt/2;i++)
    		swap(b[i],b[cnt-i-1]);
    
    	if(cnt<=0)
    		flag=1;
    
    	for(int i=0;i<cnt;i++)
    		a[i]=b[i];
    
    	len=cnt;
    }
    
    ll f[100045][2];
    
    int main()
    {
    	freopen("balance.in","r",stdin);
    	freopen("balance.out","w",stdout);
    
    	scanf("%s",mm);
    
    	len=strlen(mm);
    	for(int i=0;i<len;i++)
    		a[i]=mm[i]-'0';
    
    	cin>>n;
    
    	if(n==1)
    		{
    			for(int i=0;i<len;i++)
    				printf("%c",mm[i]);
    			return 0;
    		}
    
    	while(flag==0)
    		get();
    
    	f[0][0]=0;
    	f[0][1]=1;
    
    	//for(int i=1;i<=yu;i++)
    		//	printf("%d
    ",yushu[i]);
    	//cout<<endl;		
    	for(int i=1;i<=yu;i++)
    		{
    			f[i][0]=min(f[i-1][0]+yushu[i],f[i-1][1]+yushu[i]+1);//直接拿出
    			f[i][1]=min(f[i-1][0]+n-yushu[i],f[i-1][1]+n-yushu[i]-1);//反向拿出
    		}
    
    	printf("%lld
    ",min(f[yu][0],f[yu][1]+1));
    
    	return 0;
    }
    
  • 相关阅读:
    mysql备份与binlog
    linux释放cached
    linux下mysql迁移到其他分区
    java分析jvm常用指令
    Mac下安装WebStrom
    Final
    Spring 复习
    ubuntu 14.4安装java环境
    php复习
    java 重难点
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7700240.html
Copyright © 2011-2022 走看看