1276: 峰峰不搞G

题目

  给 n 数量的油漆,写出最大的数,每个数对应有油漆的花费。更多内容点击标题。

分析

  我读完题,就想到用动态规划,结果是Time Limit Exceed。然后看了看提交,别人的代码都很短,我就想到应该是有规律的。

  这道题目的问题是计算出最大的数,我们就要考虑什么样的数最大,显然位数越多,数肯定越大。在Simple Input中的第一组数据中,你肯定愿意写5个5(55555),而不是2个6(66),就是这个道理。

  那如果是下面这组数据呢?你该怎么办?

36
11 12 13 45 78 46 51 45 84

  你会发现,可以写3个1(111),或者3个2(222),但是正确结果应该是 321 。因此,我的方法是先用油漆写出最长位数并且花费油漆最少的数,即 111,然后再用多出来的 3 个油漆检查是不是能够增加数。从前往后检查 111 , 从9-1判断。步骤如下:

数:111		剩余油漆:3
84比11多73,剩余的油漆不够写数字9
45比11多34,剩余的油漆不够写数字8
......
13比11多2,因此可以将第一个数字1变成3,数:311 剩余油漆:1
84比11多73,剩余的油漆不够写数字9
......
13比11多3,剩余的油漆不够写数字3
12比11多1,因此可一将第二个数字变成2,数:321 剩余油漆0
第三轮,剩余的油漆不能写任何比1大的数,因此最终结果为321。

  上述大意就是,先用一定油漆写出位数最长并且使用油漆最少的数,再将多余的油漆检查是否能将数中的最高位的数字替换成更大的数字。直到最后一位数字或者无较大可替换的数字为止。

  这里提供几组测试数据,毕竟题目给的三组数据有点少,仅供参考。

36
11 12 13 45 78 46 51 45 84
1
1 1 1 1 1 1 1 1 1
2
1 1 1 1 1 1 1 1 1
17
50 40 80 61 7 19 54 48 8
17
50 40 80 61 7 19 54 9 8

  正确结果是:

321
9
99
99
99

  直接看代码吧,调试更容易看懂。

代码

/**
* time 252ms
* @author PengHao
* @version A3.1
* @date 2019-04-21 上午9:44:18
*/ import java.util.Scanner; public class Main { private Scanner sc;
private int n; // 买的油漆数量
private int[] tab; // 每个数字对应的油漆数量
private String maxNum; // 能写出的最大的数值
private int maxLen; // 能写出的数值的最大长度
private int maxIndex; // 写出最长数值且用料最少的数字的下标 public Main() {
sc = new Scanner(System.in);
tab = new int[10]; // 下标从1开始
while (sc.hasNext()) {
input();
findMaxLen();
if (0 == maxLen) { // 一个数字都不能写
System.out.println("Lihun!");
continue; // 下一组数据
}
initMaxNum();
increase();
System.out.println(maxNum); // 输出
}
sc.close();
} /**
* Input data
*/
private void input() {
n = sc.nextInt();
for (int i = 1; i <= 9; i++) {
tab[i] = sc.nextInt();
}
} /**
* Set the <b>maxLen</b> and <b>maxIndex</b>
*/
private void findMaxLen() {
maxLen = maxIndex = 0;
for (int i = 9; i > 0; i--) {
if (n / tab[i] > maxLen) { // 第i个数字能写出的位数比maxLen还多
maxIndex = i;
maxLen = n / tab[maxIndex];
} else if (n / tab[i] == maxLen) { // 写出的位数相同
if (tab[i] < tab[maxIndex]) { // 看哪个数字用的油漆少
maxIndex = i; // 写用的油漆少的那个数字
}
}
}
} /**
* Initialize <b>maxNum</b>
*/
private void initMaxNum() {
maxNum = "";
// 将最大长度得到的数值赋给结果
for (int i = 0; i < maxLen; i++) {
maxNum += maxIndex;
}
} /**
* Substituting some Numbers makes the result bigger
*/
private void increase() {
int left = n % tab[maxIndex]; // 写出了maxNum后剩下的油漆
int j;
String small, big;
// 已经写出的数值的每一位检查一遍,看能不能替换成更大的数字
for (int i = 0; i < maxLen; i++) {
j = 9; // 从9开始
// 因为可能有两个数字需要同样多的油漆,因此left可以等于0
// 如果数字j比已经写出的数字还小就不用替换了,那样只会使得结果更小
while (left >= 0 && j > maxIndex) {
if (left >= tab[j] - tab[maxIndex]) { // 剩余的油漆可以使得写出的数字更大
small = String.valueOf(maxIndex);
big = String.valueOf(j);
maxNum = maxNum.replaceFirst(small, big);
left -= tab[j] - tab[maxIndex]; // 剩余油漆变少
break; // 第i个数字已经替换,直接退出找下一位
}
j--; // 先写较大的数字,因此这里是减
}
}
} public static void main(String[] args) {
new Main();
} }

写在最后:

  1. 如需转载,请于标题下注明链接形式的wowpH的博客即可;
  2. 代码原创,如需公开引用,不能删除首行注释(作者,版本号,时间等信息)。
  3. 如果有疑问欢迎评论留言,尽力解答。

最新文章

  1. 不要听吹牛逼什么前端MVVM框架就是好,其实都是一帮没学好分层设计的搞出来的,让你彻底看清前端MVVM的本质
  2. 使用命令行执行webpagetest进行测试
  3. Oracle 11g 下载|Oracle 11g 官网下载|Oracle 11g 官网下载 带登录用户和密码
  4. mac开启服务命令
  5. ContentProvider官方教程(7)3种访问形式:批处理、异步访问、intent间接访问(临时URI权限)
  6. hdu 2988 Dark roads
  7. Extjs 4.x 得到form CheckBox的值
  8. 高可用mysql集群搭建
  9. SQLite中如何用api操作BLOB类型的字段
  10. Solrcloud,tomcat,外部zookeeper配置
  11. MapXtreme+Asp.net 动态轨迹
  12. Hadoop就是一个别人造好的轮子
  13. 详解TypScript数据类型转换
  14. as 报错
  15. echo不换行的实现
  16. 自动化部署--shell脚本--1
  17. MYSQL中常用的强制性操作(例如强制索引)
  18. hdu1839(二分+优先队列,bfs+优先队列与spfa的区别)
  19. Saving HDU hdu
  20. Maven学习----dependencies与dependencyManagement的区别(转)

热门文章

  1. hashCode 的常规协定是:
  2. sklearn中的弹性网函数 ElasticNet
  3. arcgis python 一个mxd打包mpk
  4. DOM 事件有哪些阶段?谈谈对事件代理的理解
  5. linux几种传输方式与拷贝方式的性能分析
  6. world: 对比两个文档
  7. Java Web接入支付宝扫码付款API(使用SDK证书配置properties )
  8. 单层反查BOM
  9. jQuery学习四——效果
  10. Swift学习 (三)