#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. js chart

    如何在我们项目中利用开源的图表(js chart)   最近觉得应该把自己在技术上的一些心得记录在博客里面跟大家分享,一起讨论,一起成长! 这篇随笔主要为介绍chart在项目中的运用,因为在我们看到一 ...

  2. IOS学习之路十八(通过 NSURLConnection 发送 HTTP 各种请求)

    你想通过 Http 协议向服务器发送一个 Get 的包装请求,并在这个请求中添加了一些请 求参数. 向远程服务器发送一个 GET 请求,然后解析返回的数据.通常一个 GET 请求是添加了 一些参数的, ...

  3. Windows7和Archlinux双系统硬盘安装笔记

    俗话说,好记性不如烂笔头,这些东西也都是我Google来的,做个笔记以后自己安装也方便些. 因为官方wiki的Beginners' Guide讲的非常好,大部分步骤按照wiki一步一步来就好了,这里只 ...

  4. revel框架教程之缓存和Job

    Go语言实战 - revel框架教程之缓存和Job   所有的网站应该都会有一个非常简单的需求,首页一秒之内打开. 满足的方式主要有两种: 页面静态化,效果最好,对服务器基本没负担,只要带宽足够就好了 ...

  5. Hibernate之AbstractEntityPersister

    Hibernate开发中需要根据持久层对象获取所映射的数据库表相关信息,如表名,主键,外键对象等相关系. Hibernate配置 Hibernate.cfg.xml <?xml version= ...

  6. 北京南天软件java工程师面试题

    此试题为北京南天软件java工程师面试题(部分) 一.单项选择 (1)下列关于构造方法的叙述中,错误的是(C) A.java语言规定构造方法名与类名必须相同 B.java语言规定构造方法没有返回值,但 ...

  7. 使用 App Studio 快速定制一个你自己的专属应用

    使用 App Studio 快速定制一个你自己的专属应用 如果已有做一个手机应用的想法,只需要一些简单的图片,视频,或者RSS源,就可以通过App Studio制作出你心仪的应用! App Studi ...

  8. 不想作死系列---virtualbox最小化安装centos6.5

    背景: 最近已经重装了5个系统,实在不想折腾了.于是打算在虚拟机中安装所需环境. 系统版本: 宿主机:win7 virtualbox4.3.10 centos 6.5(final) 1.下载安装vir ...

  9. IoC in Spring

    写两个关于Spring中使用IoC的小例子,一个是半动态创建Bean,另一个是全动态创建Bean,它们适合不同的应用场景. 一.半动态:在一个实际项目中遇到过这样的问题,项目组开发的某个系统具备在LE ...

  10. (*p)++ 与 *p++ 与 ++*p 拨开一团迷雾

    (*p)++ 与 *p++ 与 ++*p 拨开一团迷雾 环境:win7 IDE:DEV-C++ 编译器:GCC 1.先说++i和i++的基础 代码如下: ? 1 2 3 4 5 6 7 8 9 10 ...