#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. UITableView的style详解

    在默认的UITableViewCell中,主要有三个系统控件,分别是两个Lable和一个imageView,两个Label,imageView(始终在最左边)的布局位置可以通过下面4个设置: UITa ...

  2. WebApp之PC客户端

    开发WebApp之PC客户端 HTML5的跨平台性还是很好的,苹果.Android手机都可以用,所在最近使用Jquery Mobile开发了一个手机端应用程序,一次开发,多个平台使用. 但我们的很多客 ...

  3. django admin.py settings 操作

    dango, 怎么说呢,什么东西都内置了,什么东西都是自己的东西.用过flask, cherrypy, web.py, pyramid 等等python 框架后,再选用dango 觉得,理念有很大的区 ...

  4. jquery ready方法实现原理 内部原理

    jquery ready方法实现原理 内部原理 今天闲来无事研究研究jquery.ready()的内部实现,看JQ的源码一头雾水,由于自己很菜了,于是翻了翻牛人的播客,讲述详细,收获颇多. 先普及一下 ...

  5. PHP之语言基础01 By ACReaper

    1.PHP中的变量是不需要声明类型的,由$标识变量,变量的命名规则也是字母或者下划线开头,接着任意字符或者下划线. $PI = 3.14; $radius = 5; $cir = $PI * 2 * ...

  6. poj 1088 滑雪(贪心算法)

    思想: (贪心算法 ,看到题目是中文才做的) 先对数组中的数据进行排序,从最小的数据计算 当前的顶点的可以滑行的最大值=max(周围可达的顶点的可以滑行的最大值)+1 这样计算最后产生的路径肯定是最大 ...

  7. 初识B/S结构编程技术

    B/S结构编程语言 ASP(Active Server Page 动态服务器页面)技术 微软早期推出的B/S编程技术,出现在JSP和ASP.NET之前,PHP当时也很不稳定.ASP之前,动态网站使用G ...

  8. WPF星空效果

    效果 前阵子看到ay的蜘蛛网效果和知乎的登录页背景,觉得效果很酷.自己也想写一个.于是写着写着就变成这样了.少女梦幻的赶脚有木有.我这有着一颗少女心的抠脚大汉 实现思路 分为两个部分: 1.星星无休止 ...

  9. js获取菲波那契数列的第N个元素

    菲波那契数列,大致可以描叙为a(n) = a(n-1) + a(n-2) (a >=2).类似于这样[1, 1, 2, 3, 5, 8, 13 ...]. 具体大家可以百度一下.下面我们来用js ...

  10. Kattis -Bus Numbers

    Bus Numbers Your favourite public transport company LS (we cannot use their real name here, so we pe ...