问题 A: 最长递增子序列
给出一个序列a1,a2,a3,a4,a5,a6,a7…an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质:s1<s2<s3<…<sn并且这个子序列的长度最长。输出这个最长子序列的长度,要求时间复杂度为O(n2)。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int a[]=new int[n+1];
int b[]=new int[n+1];
for(int i=1;i<=n;i++) {
a[i]=cin.nextInt();
}
int result=solve(a,b,n);
System.out.println(result);
}
}
public static int solve(int []a,int []b,int n){
b[1]=1;
int max=b[1];
int maxlen;
for(int i=2;i<=n;i++){
maxlen=0;
for(int j=i-1;j>=1;j--){
if(a[j]<a[i]&&b[j]>maxlen){
maxlen=b[j];
}
}
b[i]=maxlen+1;
if(b[i]>max){
max=b[i];
}
}
return max;
}
}
问题 B: 构造最长递增子序列
在“最长递增子序列”的基础上对代码进行改进,输出一条最长递增子序列。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int a[]=new int[n+1];
int b[]=new int[n+1];
int c[]=new int[n+1];
int pre[]=new int[n+1];
for(int i=1;i<=n;i++) {
a[i]=cin.nextInt();
}
int r=solve(a,b,n,c,pre);
for(int i=1;i<=r;i++){
System.out.print(c[i]);
System.out.print(" ");
}
System.out.println();
}
}
public static int solve(int []a,int []b,int n,int []c,int []pre){
b[1]=1;
int max=b[1];
int maxlen;
for(int i=2;i<=n;i++){
maxlen=0;
for(int j=i-1;j>=1;j--){
if(a[j]<a[i]&&b[j]>maxlen){
maxlen=b[j];
pre[i]=j;
}
}
b[i]=maxlen+1;
if(b[i]>max){
max=b[i];
}
}
maxlen=b[1];
int lab=0;
for(int i=2;i<=n;i++){
if(b[i]>maxlen){
maxlen=b[i];
lab=i;
}
}
int i=lab;
int j=maxlen;
int num=maxlen;
while(num>0){
c[j]=a[i];
j--;
i=pre[i];
num--;
}
return max;
}
}
问题 C: 0-1背包问题
给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,背包的容量为C。如何选择装入背包的物品,可以使得装入背包中物品的总价值最大?
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int c=cin.nextInt();
int w[]=new int[n+5];
int v[]=new int[n+5];
int m[][]=new int[n+1][c+1];
int x[]=new int[n+5];
for(int i=1;i<=n;i++) {
v[i]=cin.nextInt();
}
for(int i=1;i<=n;i++) {
w[i]=cin.nextInt();
}
solve(w,v,c,n,m);
traceback(m,w,c,n,x);
System.out.println(m[1][c]);
for(int i=1;i<=n;i++){
System.out.print(x[i]);
}
System.out.println();
}
}
public static void solve(int w[],int v[],int c,int n,int m[][]){
int jmax=Math.min(w[n]-1,c);
for(int j=0;j<=jmax;j++){
m[n][j]=0;
}
for(int j=w[n];j<=c;j++){
m[n][j]=v[n];
}
for(int i=n-1;i>=1;i--){
jmax=Math.min(w[i]-1,c);
for(int j=0;j<=jmax;j++){
m[i][j]=m[i+1][j];
}
for(int j=w[i];j<=c;j++){
m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
}
}
public static void traceback(int m[][],int w[],int c,int n,int x[]){
for(int i=1;i<n;i++){
if(m[i][c]==m[i+1][c])
x[i]=0;
else {
x[i]=1;
c=c-w[i];
}
}
x[n]=(m[n][c]>0?1:0);
}
}
问题 D: X星人的基因
X星人的基因由A、B、C、D、E五种不同的结构组合而成。
如果两个性别不同的X星人的基因序列相似度大于50%,按照X星的法律他们是禁止结婚的,等于50%据说还是可以的。
那么基因的相似度怎么计算呢?分别从两个人身上取长度均为N的基因片段,如果它们的最长公共子序列为M,则相似度=M/N。是不是很简单呢?
现在给你两段X星人的基因序列片段,请你判断他们是不是可以结婚?
样例输入 Copy
8
A B C D E A B C
A C C D C B A E
6
A B C D E E
A E D C B B
0
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin =new Scanner(System.in);
while(cin.hasNext()){
int n=cin.nextInt();
if(n==0){
break;
}
cin.nextLine();//换到下一行因为cin.nextInt()无换行功能
String str1=cin.nextLine();
String str2=cin.nextLine();
str1=str1.replace(" ", "");//将字符串中的空格删去
str2=str2.replace(" ", "");
char []a1=str1.toCharArray();//将字符串转成数组
char []a2=str2.toCharArray();
int [][]c=new int[n+5][n+5];
for(int i=0;i<n+5;i++){
for(int j=0;j<n+5;j++){
c[i][j]=0;
}
}
double r=lcs(a1,a2,a1.length,a2.length,c);
double rate=r/n;
if(rate>0.5){
System.out.println("No");
}
else{
System.out.println("Yes");
}
}
}
public static double lcs(char []a1,char []a2,int l1,int l2,int [][]c){
for(int i=0;i<l1;i++){
for(int j=0;j<l2;j++){
if(a1[i]==a2[j]){
c[i+1][j+1]=c[i][j]+1;
}
else{
if(c[i+1][j]>=c[i][j+1]){
c[i+1][j+1]=c[i+1][j];
}
else{
c[i+1][j+1]=c[i][j+1];
}
}
}
}
return c[l1][l2];
}
}
这个题目由于我是用Java写的所以输入不太友好,需要一些操作将字符串变成数组。还有就是如果要得到小数被除数与除数一定要有一个是浮点型
问题 E: 出列人数
有N位同学站在一排,体育老师要请其中的(N-K)位同学出列,将剩下的K位同学从左到右依次编号为1,2,3,…K,他们的身高分别为T1,T2,T3,…TK,要求满足T1<T2<T3<…<TK。已知N位同学的身高,请设计一个算法,计算最少需要几位同学出列可使得剩下的同学满足上述要求。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int a[]=new int[n+1];
int b[]=new int[n+1];
for(int i=1;i<=n;i++) {
a[i]=cin.nextInt();
}
int result=solve(a,b,n);
int count=n-result;
System.out.println(count);
}
}
public static int solve(int []a,int []b,int n){
b[1]=1;
int max=b[1];
int maxlen;
for(int i=2;i<=n;i++){
maxlen=0;
for(int j=i-1;j>=1;j--){
if(a[j]<a[i]&&b[j]>maxlen){
maxlen=b[j];
}
}
b[i]=maxlen+1;
if(b[i]>max){
max=b[i];
}
}
return max;
}
}
问题 F: XP的午餐
XP每天都会思考一个问题,今天午餐去哪里吃?这是一个很重要的问题,这会影响到他下午的体力值。他的午餐预算是M元,现在有N种菜品,每一种菜品的价格和能够提供的体力值已知(每种菜品只能选择一次),请问如何选择菜品能够让XP下午的体力值最大呢?
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int c=cin.nextInt();
int n=cin.nextInt();
int w[]=new int[n+5];
int v[]=new int[n+5];
int m[][]=new int[n+1][c+1];
int j=1,k=1;
for(int i=0;i<2*n;i++) {
if(i%2==0){
w[j]=cin.nextInt();
j++;
}
else{
v[k]=cin.nextInt();
k=k+1;
}
}
solve(w,v,c,n,m);
System.out.println(m[1][c]);
}
}
public static void solve(int w[],int v[],int c,int n,int m[][]){
int jmax=Math.min(w[n]-1,c);
for(int j=0;j<=jmax;j++){
m[n][j]=0;
}
for(int j=w[n];j<=c;j++){
m[n][j]=v[n];
}
for(int i=n-1;i>=1;i--){
jmax=Math.min(w[i]-1,c);
for(int j=0;j<=jmax;j++){
m[i][j]=m[i+1][j];
}
for(int j=w[i];j<=c;j++){
m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
}
}
}