UVa12105
来源:互联网 发布:3d软件培训 编辑:程序博客网 时间:2024/06/14 23:08
题目链接
简介:
用n根火柴拼出尽量大的能被m整除的数
分析:
有一种非常显而易见的dp方法:
f[i][j]表示用i根火柴拼出的“%m是j”的最大整数
转移方程:
f[i+c[k]][(j*10+k)%m]=max{f[i][j]+k}
时间复杂度是O(10*nm),看上去好像非常优秀
但是这样的状态值是高精度(能拼成的数可能很大),因此实际计算量非常大
(再说有人愿意随手写一个高精度吗。。。)
下面就说一个有点难度,但是效率很高的算法:
f[i][j]表示拼出“%m是j的i位数”所用的最少火柴
转移方程:
f[i+1][(j*10+k)%m]=min{f[i][j]+c[k]}
那么我们怎么根据f数组确定解呢
首先我们先确定下来最高位(在转移的时候顺便维护一下就好了)
之后我们从高位向低位枚举每一位的数字
举个简单的例子:m=7,并且已经确定最高位是3
首先试着让最高位为9,如果我们能够摆出9xx这样的合法数字,那么ta一定是最大的
是否可以摆出9xx呢?
因为900%7=4,因此后两位%7的余数应该是3
如果d[2][3]+c[9]<=n,那么最高位就可以是9
重复上述过程,直到所有数字都被确定
在计算过程中,我们需要快速算出形如 x000… 的整数%m的答案,这需要我们一开始预处理一下
tip
d<—INF,d[0][0]=0
注意
我们计算出来的f只是辅助构造解的
我们在构造解的时候运用贪心的思想,让位数尽量多,每一位尽量大
所以只要符合
d[now-1][(limit-c[k]+m)%m]+c[k]<=n
我们就可以确定这一位是k
//这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int INF=0x33333333;int c[10]={6,2,5,5,4,5,6,3,7,6};int d[100][3002];int n,m,len,maxx,rst[100][10];void doit(){ int i,j,k; d[0][0]=0; //不要忘了初始化 for (i=0;i<=9;i++) { d[1][i%m]=min(d[1][i%m],c[i]); if (d[1][i%m]<=n&&i%m==0) maxx=1; } for (i=1;i<len;i++) for (j=0;j<m;j++) if (d[i][j]) for (k=0;k<=9;k++) { int v=(j*10+k)%m; d[i+1][v]=min(d[i][j]+c[k],d[i+1][v]); if (d[i+1][v]<=n&&v==0) maxx=max(maxx,i+1); //最高位 }}void print(){ int ans[100],limit=m; int S=n; //可用的火柴 for (int i=maxx;i>=1;i--) for (int j=9;j>=0;j--) //从大到小枚举这一位上的数 { int r=S-c[j]; //剩下的位数能够使用的火柴数 int num=(limit-rst[i][j]+m)%m; //剩下的位数%m的余数 if (d[i-1][num]<=r) //只要可行即可 { ans[i]=j; S-=c[j]; limit=num; break; } } for (int i=maxx;i>=1;i--) printf("%d",ans[i]); printf("\n");}int main(){ int cnt=0; while (scanf("%d",&n)!=EOF&&n) { scanf("%d",&m); memset(d,0x33,sizeof(d)); memset(rst,0,sizeof(rst)); for (int i=1;i<=9;i++) rst[1][i]=i%m; //预处理 x000 %m for (int i=2;i<100;i++) for (int j=1;j<=9;j++) { int num=(rst[i-1][j]*10)%m; rst[i][j]=num; } printf("Case %d: ",++cnt); len=n/2+1; maxx=0; doit(); if (d[maxx][0]<=n&&maxx) print(); else printf("-1\n"); } return 0;}
阅读全文
0 0
- UVa12105
- uva12105 【DP】
- uva12105 Bigger is Better
- uva12105 - Bigger is Better 大数
- UVA12105 - Bigger is Better(DP)
- 例题9-22 越大越好 UVa12105
- Unity3D游戏场景之播放音频文件
- Android FlowLayout流布局
- webstorm打开后 一直停留在scanning files to index
- java.util.ConcurrentModificationException 与集合删除
- 斯坦福机器学习笔记 第3周 六、逻辑回归(一)
- UVa12105
- Search Graph Nodes
- Qt 之 返回exec()
- PHP 运用 XMLWriter 读写 xml 文件
- Windows操作HID设备的API
- KCF目标跟踪方法总结与分析
- Python机器学习:numpy的应用之基本操作命令
- PhotoShop CC 2017软件工具面板使用---矩形选框工具
- hdu 5120 Intersection(求相交圆的面积)