#1043 : 完全背包 20160516

时间限制:20000ms
单点时限:1000ms
内存限制:256MB

描述

且说之前的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励的时刻了!

等等,这段故事为何似曾相识?这就要从平行宇宙理论说起了………总而言之,在另一个宇宙中,小Ho面临的问题发生了细微的变化!

小Ho现在手上有M张奖券,而奖品区有N种奖品,分别标号为1到N,其中第i种奖品需要need(i)张奖券进行兑换,并且可以兑换无数次,为了使得辛苦得到的奖券不白白浪费,小Ho给每件奖品都评了分,其中第i件奖品的评分值为value(i),表示他对这件奖品的喜好值。现在他想知道,凭借他手上的这些奖券,可以换到哪些奖品,使得这些奖品的喜好值之和能够最大。

提示一: 切,不就是0~1变成了0~K么

提示二:强迫症患者总是会将状态转移方程优化一遍又一遍

提示三:同样不要忘了优化空间哦!

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第一行为两个正整数N和M,表示奖品的种数,以及小Ho手中的奖券数。

接下来的n行描述每一行描述一种奖品,其中第i行为两个整数need(i)和value(i),意义如前文所述。

测试数据保证

对于100%的数据,N的值不超过500,M的值不超过10^5

对于100%的数据,need(i)不超过2*10^5, value(i)不超过10^3

输出

对于每组测试数据,输出一个整数Ans,表示小Ho可以获得的总喜好值。

样例输入
5 1000
144 990
487 436
210 673
567 58
1056 897
样例输出
5940

思路:看题目给出的提示会比较清楚。
import java.util.Scanner;

public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int m = sc.nextInt();
int[] need = new int[n+1];
int[] value = new int[n+1];
for (int i = 1; i <= n; i++) {
need[i] = sc.nextInt();
value[i] = sc.nextInt();
}
int[][] max = new int[2][m+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i % 2 == 0) {
if (j >= need[i]) {
max[0][j] = Math.max(max[0][j - need[i]] + value[i], max[1][j]);
} else {
max[0][j] = max[1][j];
}
} else {
if (j >= need[i]) {
max[1][j] = Math.max(max[1][j - need[i]] + value[i], max[0][j]);
} else {
max[1][j] = max[0][j];
}
}
}
}
if (n % 2 == 0)
System.out.println(max[0][m]);
else
System.out.println(max[1][m]);
}
}
}

#1038 : 01背包 20160512

时间限制:20000ms
单点时限:1000ms
内存限制:256MB

描述

且说上一周的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励的时刻了!

小Ho现在手上有M张奖券,而奖品区有N件奖品,分别标号为1到N,其中第i件奖品需要need(i)张奖券进行兑换,同时也只能兑换一次,为了使得辛苦得到的奖券不白白浪费,小Ho给每件奖品都评了分,其中第i件奖品的评分值为value(i),表示他对这件奖品的喜好值。现在他想知道,凭借他手上的这些奖券,可以换到哪些奖品,使得这些奖品的喜好值之和能够最大。

提示一:合理抽象问题、定义状态是动态规划最关键的一步

提示二:说过了减少时间消耗,我们再来看看如何减少空间消耗

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第一行为两个正整数N和M,表示奖品的个数,以及小Ho手中的奖券数。

接下来的n行描述每一行描述一个奖品,其中第i行为两个整数need(i)和value(i),意义如前文所述。

测试数据保证

对于100%的数据,N的值不超过500,M的值不超过10^5

对于100%的数据,need(i)不超过2*10^5, value(i)不超过10^3

输出

对于每组测试数据,输出一个整数Ans,表示小Ho可以获得的总喜好值。

样例输入
5 1000
144 990
487 436
210 673
567 58
1056 897
样例输出
2099

思路:题目提示所给思路说的非常清楚。首先得想到动态规划这种做法,因为这个问题符合动态规划的两个特征重复的子问题和无后效性(具体见提示一)。动态规划时,关键就是在第n个奖品的兑换,有兑换和不兑换两种状态(对应着01背包的1和0),兑换和不兑换的总喜好值较大值就是到第n个奖品时最大总喜好值。

也就是公式:max[i][j] = max{value[i] + max[i-1][j-need[i]], max[i-1][j]},

需要注意的就是这只在j>= need[i]时,才成立,j < need[i]时 max[i][j] = max[i-1][j]。

所以最容易想到 int[][] max = new int[n+1][m+1];然后两个循环求出max[n][m],这样一来空间复杂度就不够简化了。进一步思考发现max只有前后的依赖关系,所以只用保证前一个保存下来就能求出后一个了,所以可简化为 O(2*m)的空间复杂度。提示二中还给出了O(m)的空间复杂度,可以继续思考。

import java.util.Scanner;

public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int m = sc.nextInt();
int[] need = new int[n+1];
int[] value = new int[n+1];
for (int i = 1; i <= n; i++) {
need[i] = sc.nextInt();
value[i] = sc.nextInt();
}
//MTE n*m的数组,内存超过限制
/* int[][] max = new int[n+1][m+1];
for (int i = 1; i <= n; i++) {
for (int j = 1;j <= m; j++) {
if (j >= need[i]) {
max[i][j] = Math.max(value[i] + max[i-1][j-need[i]], max[i-1][j]);
} else {
max[i][j] = max[i-1][j];
}
}
}
System.out.println(max[n][m]);
*/
//只用 2*m的空间,因为max只有前后的依赖关系,已经可以AC了
/* int[][] max = new int[2][m+1];
for (int i = 1; i <= n; i++) {
for (int j = 1;j <= m; j++) {
if (i %2 == 0) {
if (j >= need[i]) {
max[0][j] = Math.max(value[i] + max[1][j-need[i]], max[1][j]);
} else {
max[0][j] = max[1][j];
}
} else {
if (j >= need[i]) {
max[1][j] = Math.max(value[i] + max[0][j-need[i]], max[0][j]);
} else {
max[1][j] = max[0][j];
}
}
}
}
if (n % 2 == 0)
System.out.println(max[0][m]);
else
System.out.println(max[1][m]);
*/
//只用m的空间,实在是没理解
int[] max = new int[m+1];
for (int i = 1; i <= n; i++) {
for (int j = m; j >= need[i]; j--) {
max[j] = Math.max(max[j], max[j-need[i]]+value[i]);
}
}
System.out.println(max[m]);
}
}
}

思考了一下,感觉贪心算法也能实现,但是想到的复杂度会略高:原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。

#1032 : 最长回文子串  20160508

时间限制:1000ms
单点时限:1000ms
内存限制:64MB

描述

小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”

小Ho奇怪的问道:“什么叫做最长回文子串呢?”

小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”

小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?

小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”

提示一 提示二 提示三 提示四

样例输入
3
abababa
aaaabaa
acacdas
样例输出
7
5
3

个人认为这篇博客分析的比较好,虽然我是按照提示一步一步写出来的。

提交时发现必须在头尾加入两个不同的特殊字符,我下面这种方式没有在头尾加,提交we了,没想明白(详见代码中/**/注释的那一段)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; public class Main {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = "";
while ((s = br.readLine()) != null) {
int t = Integer.parseInt(s);
for (int i = 0;i < t;i++) {
String str = br.readLine();
StringBuilder sb = new StringBuilder();
sb.append("$#");
//在原字符串每个相邻字符串中间插入'#'
for (int j = 0;j < str.length();j++) {
sb.append(str.charAt(j)+"#");
}
sb.append("&");
str = sb.toString();
/*把添加特殊字符那一段修改一下就不对了,没想明白,我看出来的现象是必须在头尾加入两个不同的特殊字符,
我下面这种方式没有在头尾加,提交we了
    

//在原字符串每个相邻字符串中间插入'^'
for (int j = 0;j < str.length()-1;j++) {
sb.append(str.charAt(j)+"^");
}
sb.append(str.charAt(str.length()-1));
str = sb.toString();

*/
int ans = 1,maxj = 0,maxjk = 0,pos = 0;
int[] ls = new int[str.length()];
for (int j = 0;j < str.length();j++) {
//获得当前j为中心的回文子串的最小长度
int k = 0;
if (2*maxj-j < 0) {
k = Math.min(0, ls[maxj]-2*(j-maxj))/2;
} else {
k = Math.min(ls[2*maxj-j], ls[maxj]-2*(j-maxj))/2;
}
k = k > 0 ? k : 0;
ls[j] += 2*k+1;
k++;
while (((j-k) >= 0) && ((j+k) < str.length())) {
if (str.charAt(j-k) == str.charAt(j+k)) {
ls[j] += 2; //记录以每一个字符为中心时的最大回文长度
if (j+k > maxjk) {
maxj = j; //记录使右边界最大的j
maxjk = j+k; //记录右边界的最大值
}
k++;
} else {
break;
}
}
//更新最大回文子串长度与中心字符的位置
if (ls[j] > ans) {
ans = ls[j];
pos = j;
}
}
//去掉其中的特殊字符'^'
if (pos % 2 == 0) {
if (ans >= 3) {
ans = ans-2*((ans-3)/4+1);
}
} else {
ans = ans-2*((ans-1)/4)-1;
}
System.out.println(ans);
}
}
}
}
 

HihoCoder的更多相关文章

  1. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

  2. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

  3. hihoCoder太阁最新面经算法竞赛15

    hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...

  4. 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II

    http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ...

  5. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  6. 【hihoCoder】1148:2月29日

    问题:http://hihocoder.com/problemset/problem/1148 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 思路: 1. 将问题转换成求两个日 ...

  7. 【hihoCoder】1288 : Font Size

    题目:http://hihocoder.com/problemset/problem/1288 手机屏幕大小为 W(宽) * H(长),一篇文章有N段,每段有ai个字,要求使得该文章占用的页数不超过P ...

  8. 【hihoCoder】1082: 然而沼跃鱼早就看穿了一切

      题目:http://hihocoder.com/problemset/problem/1082 输入一个字符串,将其中特定的单词替换成另一个单词   代码注意点: 1. getline(istre ...

  9. 【hihoCoder】1121:二分图一·二分图判定

      题目   http://hihocoder.com/problemset/problem/1121 无向图上有N个点,两两之间可以有连线,共有M条连线. 如果对所有点进行涂色(白/黑),判定是否存 ...

  10. 【hihoCoder】1036 Trie图

    题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...

随机推荐

  1. 使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑

    翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑 Part 3: 设计逻辑层:核心开发 如前所述,我们的解决方案 ...

  2. python 字符串(汉语)获得MD5编码

    MD5即Message-Digest Algorithm 5(消息摘要算法第五版)的简称,是当前计算机领域用于确保信息传输完整一致而广泛使用的散列算法之一(又译哈希算法.摘要算法等),主流编程语言普遍 ...

  3. IOS开发之路三(XML解析之GDataXML的使用)

    最近再做一个项目需要用到xml的解析.今天查了一些资料自己做了一个小demo.纯OC没有界面.. 在IOS平台上进行XML文档的解析有很多种方法,在SDK里面有自带的解析方法,但是大多情况下都倾向于用 ...

  4. 自定义的UIAlertView不能在iOS7上正常显示

    众所周知,当伟大的iOS7系统发布后,表扬的一堆.谩骂的也一片,而对于我们程序员来说最关心的莫过于低版本系统上的程序在搞版本系统上的兼容性问题了. 在iOS6.1几之前,当我们想要做一些提醒用户或临时 ...

  5. cubieboard 配置WIFI

    1.先装好驱动程序 2.ifconfig查看无线网卡的名称,比如 3.修改/etc/networking/interfaces,配置 wpa-essid填写WIFI名称 wpa-psk填写密码 4. ...

  6. node包管理器

    NPM小结   nodejs的出现,可以算是前端里程碑式的一个事件,它让前端攻城狮们摆脱了浏览器的束缚,踏上了一个更加宽广的舞台.前端的可能性,从此更加具有想象空间. 随着一系列基于nodes的应用/ ...

  7. Java笔记:内部类

    1.把一个类放在另一类内部定义,这个定义在其他类里面的类就叫做内部类,包含内部类的类叫做外部类.内部类成员可以直接访问外部类的私有数据,但是外部类不能访问内部类的实现细节. 2.非静态内部类(没有st ...

  8. django model Foreign key usage 关系型数据库 ORM

    django 的模型 from django.db import models""" A model pair to map car and its manufactur ...

  9. 最新FFMPEG解码流程

    FFMPEG解码流程: 1. 注册所有容器格式和CODEC:  av_register_all() 2. 打开文件:                    av_open_input_file() 3 ...

  10. 基于数据库的自动化生成工具,自动生成JavaBean、自动生成数据库文档等(v4.1.2版)

            目录:            第1版:http://blog.csdn.net/vipbooks/article/details/51912143            第2版:htt ...