ZOJ 1108 FatMouse's Speed 动态规划

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=108

题目大意:证明老鼠重量越重,速度越慢,给你一组老鼠的数据(包括重量和速度),要求输出满足前面条件的最长的子序列的老鼠编号

首先,按照老鼠的重量进行升序和速度的降序排列;

然后,根据动态方程求解

len[0]=1;len[i]=max{len[j]}+1 (0<=j<i)

最后,输出老鼠的编号顺序,为了能够输出顺序的编号,所以要给老鼠一个index和preIndex,最后输出时最好的方法是采用递归的方式

注意:

1.题目的结束是以文件结尾为结束符,在C和C++中是 EOF,但是在Java里文件结束是null,用Scanner和 BufferedReader 都可以,接着判断
(str = br.readLine()).equals("")就可以了;
或者是 !(str = sin.nextLine()).equals("")
2.使用BufferedReader每次读取的都是一行数据,这里我要得到的是以空格隔开来的两个数字,可以使用StringTokenizer,也可以使用Scanner,当然
这道题目其实使用String的各种操作也是可以实现的。

  

int w2=Integer.parseInt(str.substring(0, str.indexOf(" ")));//区别在这里

  int s2=Integer.parseInt(str.substring(str.indexOf(" ")+1));

我的Java代码:【注意:结果是TLE,我实在是没有办法】

/**
* 修改排序方法,使用Collections.sort
* 修改设置preIndex的方法和输出方式
* 结果:TLE
*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class ZOJ1108_4 {

public static int n;// 记录老鼠的数目
public static int[] len;// 记录以原序列中第i个老鼠结尾的最长的子序列
public static int maxlen, maxIndex;// 分别表示最大长度和最后的老鼠的index
public static ArrayList<Mouse> mice = new ArrayList<Mouse>();// 记住要new,不然会报空指针

public static void main(String[] args) throws Exception {
BufferedReader br
= new BufferedReader(new InputStreamReader(System.in));
n
= 0;
String str;
while (!(str = br.readLine()).equals("")) {
Scanner sin
= new Scanner(str);
int w = sin.nextInt();
int s = sin.nextInt();
Mouse m
= new Mouse(n + 1, w, s);
n
++;
mice.add(m);
}
Collections.sort(mice,
new Comparator<Mouse>() {
public int compare(Mouse o1, Mouse o2) {
if (o1.weight > o2.weight) {
return 1;
}
else if (o1.weight == o2.weight && o1.speed < o2.speed) {
return 1;
}
else {
return -1;
}
}
});
dpSpeed();
System.out.println(maxlen);
output(maxIndex);
}

//根据老鼠的速度进行dp
private static void dpSpeed() {
len
= new int[n];
int i, j, k;
maxlen
= 0;
maxIndex
= 0;
len[
0] = 1;
mice.get(
0).preIndex = 0;
for (i = 1; i < n; i++) {
len[i]
= 1;
for (j = 0; j < i; j++) {
if (mice.get(i).speed < mice.get(j).speed
&& mice.get(i).weight > mice.get(j).weight) {
if (len[j] >= len[i]) {// 注意这里可以等于,也许刚好满足条件的那个就是长度为1[可以调试]
len[i] = len[j] + 1;
mice.get(i).preIndex
= j;
}
}
}
}
for (k = 0; k < n; k++) {
if (len[k] > maxlen) {
maxlen
= len[k];
maxIndex
= k;
}
}
}

//用递归的方式输出
private static void output(int index) {
if(len[index]==1){
System.out.println(mice.get(index).index);
}
else{
output(mice.get(index).preIndex);
System.out.println(mice.get(index).index);
}
}
}

class Mouse {
int index;// 记录该老鼠是原序列的第几位
int weight;// 记录重量和速度
int speed;
int preIndex;// 记录该老鼠在得到的序列中的上一个老鼠的index

public Mouse() {

}

public Mouse(int index, int weight, int speed) {
this.index = index;
this.weight = weight;
this.speed = speed;
}
}

换了一种方式,结果是RE,不知道哪里出错了

/**
* 修改排序方法,使用Collections.sort
* 修改设置preIndex的方法和输出方式
* 修改了得到输入数据的方法
* 结果:RE
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class Main{

public static int n;// 记录老鼠的数目
public static int[] len;// 记录以原序列中第i个老鼠结尾的最长的子序列的长度
public static int maxlen, maxIndex;// 分别表示最大长度和最后的老鼠的index
public static ArrayList<Mouse> mice = new ArrayList<Mouse>();// 记住要new,不然会报空指针

public static void main(String[] args){
Scanner sin
=new Scanner(System.in);
n
= 0;
String str;
while (!(str = sin.nextLine()).equals("")) {//利用nextLine方法也是可以的!
int w2=Integer.parseInt(str.substring(0, str.indexOf(" ")));//区别在这里
int s2=Integer.parseInt(str.substring(str.indexOf(" ")+1));
Mouse m
= new Mouse(n + 1, w2, s2);
n
++;
mice.add(m);
}
Collections.sort(mice,
new Comparator<Mouse>() {
public int compare(Mouse o1, Mouse o2) {
if (o1.weight > o2.weight) {
return 1;
}
else if (o1.weight == o2.weight && o1.speed < o2.speed) {
return 1;
}
else {
return -1;
}
}
});
dpSpeed();
System.out.println(maxlen);
output(maxIndex);
}

//根据老鼠的速度进行dp
private static void dpSpeed() {
len
= new int[n];
int i, j, k;
maxlen
= 0;
maxIndex
= 0;
len[
0] = 1;
mice.get(
0).preIndex = 0;
for (i = 1; i < n; i++) {
len[i]
= 1;
mice.get(i).preIndex
=i;
for (j = 0; j < i; j++) {
if (mice.get(i).speed < mice.get(j).speed
&& mice.get(i).weight > mice.get(j).weight) {
if (len[j] >= len[i]) {// 注意这里可以等于,也许刚好满足条件的那个就是长度为1[可以调试]
len[i] = len[j] + 1;
mice.get(i).preIndex
= j;
}
}
}
}
for (k = 0; k < n; k++) {
if (len[k] > maxlen) {
maxlen
= len[k];
maxIndex
= k;
}
}
}

//用递归的方式输出
private static void output(int index) {
if(len[index]==1){//巧妙之处:最后的那个的len[]==1
System.out.println(mice.get(index).index);
}
else{
output(mice.get(index).preIndex);
System.out.println(mice.get(index).index);
}
}
}

class Mouse {
int index;// 记录该老鼠是原序列的第几位
int weight;// 记录重量和速度
int speed;
int preIndex;// 记录该老鼠在得到的序列中的上一个老鼠的index

public Mouse() {

}

public Mouse(int index, int weight, int speed) {
this.index = index;
this.weight = weight;
this.speed = speed;
}
}

  

解题时我参考了网上一位同学的方法,很是不错啊,和我的差不多,不过输出我是参考他的

他用的是C++,顺利 AC ,我们的算法时间复杂度都是 O(n^2)。。。【详情可见我的博客中的另外一篇博文】

虽说还有一种更好的算法 O(nlog(n)),但是我怎么都没写出来,因为那个比较的方式太复杂了点

#include <iostream>
#include
<algorithm>
#define MAX 1005
using namespace std;

struct Mice
{
int id;
int weight;
int speed;
int pre;
};


bool cmp(const Mice& a, const Mice& b)
{
if (a.weight < b.weight)
return true;
else if (a.weight == b.weight)
return a.speed > b.speed;
else
return false;
}

int num[MAX];
Mice mice[MAX];

void output(int);

int main()
{
int count = 0;

while (cin >> mice[count].weight >> mice[count].speed)
{
mice[count].id
= count+1;
count
++;
}


sort(mice, mice
+count, cmp);

num[
0] = 1;
mice[
0].pre = 0;

for (int i = 1; i < count; i++)
{
num[i]
= 1;
mice[i].pre
= i;

for (int j = 0; j < i; j++)
{
if (mice[i].weight > mice[j].weight && mice[i].speed < mice[j].speed)
{
if (num[i] < num[j]+1)
{
num[i]
= num[j]+1;
mice[i].pre
= j;
}
}
}

}

int max_index = 0;
for (int i = 1; i < count; i++)
if (num[i] > num[max_index])
max_index
= i;

cout
<< num[max_index] << endl;

output(max_index);
return 0;
}


void output(int index)
{
if (num[index] == 1)
cout
<< mice[index].id << endl;
else
{
output(mice[index].pre);
cout
<< mice[index].id << endl;
}
}

  

转载于:https://www.cnblogs.com/yinger/archive/2011/07/21/2113235.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值