1. 假设某卡牌类游戏里面,你搜集了 17 种卡牌,每种卡牌的攻击伤害率从小到大排列分别 为 1,4,9,… ,289,即 n 的平方(1<=n<=17,n 为正整数),并且每种卡牌的数量足够 多,现在请你计算出有多少种卡牌组合方式使得卡牌的总攻击率为 m(m<=500)比如 m=10, 那么有 4 种组合卡牌的方式,相同种卡牌可重复出现;
【分析】 此类问题属于组合计数问题,在组合数学中,最经典的问题就是给定n个不同类型的砝码(单个类型的砝码数不固定),求当给定一个值时,求解能够完成称重的所有组合数。而此类问题一般可通过“生成函数(母函数)”的方法来解决。但这种方法再实际编程过程中,往往需要求解出一个通向式。故在此,我们将选取另一种方法来解决该问题。
首先,定义函数: findNumber(E,n,energy) , 其中 n = Math.sqrt(E) ; 该函数表示当总攻击率为E时,采用前n种卡牌进行组合,最终能达到目标的组合数。而对于上述问题,可以分解为两个子问题:①使用前n-1种选择组成E的组合数 ②至少使用第n种选择一次时组成m的组合数。 这样问题就变得迎刃而解了。采用递归的方式,将上述子问题相加即可得到最终的结果。
以下为该问题的JAVA代码:
import java.util.Scanner;
public class Main {
public int findNumber(int E, int n, int[] energy) {
if(E == 0)
return 1;
if( E < 0 || n <= 0)
return 0;
return findNumber(E, n-1, energy) + findNumber(E - energy[n], n, energy);
}
public static void main(String[] args) {
int[] energy = new int[18];
for(int i=0; i
2.题目要求:
输入: 第一行三个数n,m,k,分别表示n个数,取m个,且m个中的任意两个位置差要大于等于K,接下来一行,有n个整数,表示序列上的每个数。
输出: 最大和
数据范围: n<=10000, m<=100,m<=n
Sample Input
4 2 2
3 4 -5 1
Sample Output
5
【分析】首先,请注意题目中标红的文字! 对于本体,很容易想到解题方向:动态规划;也很容易找到动态规划中的状态转移方程。在这里,我们首先定义F[n][m],表示从前n个数中,取m个数,并且满足位置差条件的数之和。那么对于动态规划问题,第一步先确定“状态转移方程”,在给定条件下(位置差),状态转移方程可记为:
F[ i ] [ j ] = max ( F[ i - 1 ] [ j ] ,F[ i - k ] [ j - 1 ] )
即分两种情况讨论,①不取第i个数,在前i-1个数中找和最大的 ②取第i个数,在前i - k 个数中找和最大的 ; 最后比较①②两种情况,将大的一方作为当前情况的和最大。当状态转移方程确定后,需要确定初始状态的值,而这个值可手动给出,即:F[0][0], F[1][0],....,F[n-1][0] 和 F[0][1],F[0][2],.....,F[0][m-1] 。
当状态转移方程和初始状态确定后,本题的问题也就迎刃而解了。
以下为该问题的JAVA代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()) {
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
int[] A = new int[n];
int[][] F = new int[n][m];
for(int i=0; i0 && F[i-1][0]0 && F[i-1][0]>=A[i])
F[i][0] = F[i-1][0];
}
for (int j = 1; j < m; j++) {
F[0][j] = 0;
}
int reslut = getMaxData(A, F, n, m, k);
System.out.println(reslut);
}
}
private static int getMaxData(int[] A, int[][] F, int n, int m, int k) {
k--;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
F[i][j] = F[i-1][j];
if(i >= k) {
F[i][j] = F[i-1][j] > (F[i-k][j-1] + A[i]) ? F[i-1][j] : (F[i-k][j-1] + A[i]);
}
}
}
return F[n-1][m-1];
}
}
3.最长公共子序列
【分析】
① 序列str1和序列str2
·长度分别为m和n;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while( sc.hasNext()) {
String A = sc.nextLine();
String B = sc.nextLine();
char[] ca = A.toCharArray();
char[] cb = B.toCharArray();
int la = A.length();
int lb = B.length();
int[][] F = new int[la+1][lb+1];
for(int i=0; i t2)
F[m][n] = t1;
else
F[m][n] = t2;
}
}
}
int tm = la, tn = lb;
StringBuffer sb = new StringBuffer();
while(tm > 0 && tn > 0) {
if(ca[tm-1] == cb[tn-1]) {
sb.insert(0, ca[tm-1]);
tm--;
tn--;
}
else if (F[tm-1][tn] > F[tm][tn-1])
tm--;
else
tn--;
}
System.out.println(F[la][lb]);
System.out.println(sb.toString());
}
}
}
2
import java.util.Scanner;
public class Main {
private static int[][] getLCS(String A, String B) {
char[] ca = A.toCharArray();
char[] cb = B.toCharArray();
int la = A.length();
int lb = B.length();
int[][] F = new int[la+1][lb+1];
for(int i=0; i t2)
F[m][n] = t1;
else
F[m][n] = t2;
}
}
}
return F;
}
private static void printLCS(int[][] F, String A, String B) {
char[] ca = A.toCharArray();
char[] cb = B.toCharArray();
int tm = A.length();
int tn = B.length();
StringBuffer sb = new StringBuffer();
while(tm > 0 && tn > 0) {
if(ca[tm-1] == cb[tn-1]) {
sb.insert(0, ca[tm-1]);
tm--;
tn--;
}
else if (F[tm-1][tn] > F[tm][tn-1])
tm--;
else
tn--;
}
System.out.println(F[A.length()][B.length()]);
System.out.println(sb.toString());
}
private static int toPalindromeString(String data) {
StringBuffer sb = new StringBuffer(data);
String reverse_data = sb.reverse().toString();
int[][] F = getLCS(data,reverse_data);
int original_length = data.length();
return original_length - F[original_length][original_length];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while( sc.hasNext()) {
String data = sc.nextLine();
int number = toPalindromeString(data);
System.out.println(number);
}
}
}
比较I和II的结果,取较小的返回!
import java.util.Scanner;
/*回文字符串*/
public class Main {
private static int toPalindromeString_other2(char[] c, int m, int n) {
if(m >= n)
return 0;
if(m+1 == n)
return 1;
if(c[m] == c[n])
return 0;
else {
int left = toPalindromeString_other2(c,m,n-1)+1;
int right = toPalindromeString_other2(c,m+1,n)+1;
if(left > right)
return right;
else
return left;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while( sc.hasNext()) {
String data = sc.nextLine();
int number = toPalindromeString_other2(data.toCharArray(),0,data.length()-1);
System.out.println(number);
}
}
}
import java.util.Scanner;
public class main {
private static int getLIS(String data) {
if(data.length() == 0)
return 0;
char[] d = data.toCharArray();
int len = d.length;
int[] F = new int[len];
F[0] = 1;
for(int i=1; i d[i-1])
F[i] = F[i-1] + 1;
else if (d[i] == d[i-1])
F[i] = F[i-1] ;
else {
int tmp = 0;
int j = i-1;
while(j>=0) {
if(d[i] > d[j]) {
tmp = F[j] + 1;
break;
}
else if (d[i] == d[j]) {
tmp = F[j];
break;
}
j--;
}
if(tmp > F[i-1])
F[i] = tmp;
else
F[i] = F[i-1];
}
}
return F[len - 1];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while( sc.hasNext()) {
String data = sc.nextLine();
System.out.println(getLIS(data));
}
}
}