一道JAVA游戏算法题 一个游戏:你有n张防御卡Di,价值相应为wi,防御能力为di。你的对手有进攻卡Aj,进攻能力为aj。如果Di与Aj相遇,且di<aj时,防御卡就死掉。你的任务是安排一种匹配, 使得存活防御卡的剩余价值最大。给出你的算法,并说明正确性。求指教 求算法 求代码,这个题目看了不知道从何下手,是不是要想田忌赛马那样做呢? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我有个想法 不知对错先把 A 按攻击力非降序排好序在把 B 一个个取出来用2分找到 A 中那个不能杀掉B且是最大的那个如果这个位置目前还没匹配上 B, 那么把当前 B 与 A 匹配如果这个位置有其他的 B 牌,那么比较这2张B牌的价值,把价值大的与A匹配价值小的那个B牌与当前A之前的其他A中的B牌比较(能不被当前A杀死的必然不能比之前的A杀死)把价值小的那个B牌找到一个合适的位置与A匹配 能不能这样对Aj中的任何一个,按下面规则匹配Dj1、如果Dj中有比Aj大的牌,则选择与Aj牌攻击力相差最小的一张牌去匹配..2、如果Dj中没有比当前Aj牌大的牌,则选择Dj中剩余的最小的一张去匹配... 上面错了,漏看了,DJ的牌还有个价值WI...要求的是剩余价值最大.. 我个人的想法:无法证明是最优解,但是也找不出哪里错了...1、把Dj牌按 价值--防御的顺序 逆序排列 (价值最高的牌需要最优先保证存活)2、把Aj牌按升序排列 (这个升降序 无所谓,反正要排次)3、按顺序遍历Dj牌,对于每个牌,优先找与其防御值最近但是不大于该防御值的Aj牌匹配。如果找不到则将其与攻击最大的牌匹配(废牌要最佳利用嘛);代码和执行结果如下....写的很烂随便看看,我也不知道怎么证明这个思路是对的或者错的...public class zzz { //第一位表示防御值,第二位表示价值 private static int[] Dj = new int[] { 11, 23, 45, 22, 12, 55, 42, 56, 91 }; private static int[] Aj = new int[] { 11, 4, 2, 4, 5, 6, 7, 8, 4 }; private static int totalVal = 0; public static void main(String args[]) { //按价值-防御 逆序对原数组排序 for (int i = 0; i < Dj.length; i++){ for(int j = i+1; j<Dj.length ;j++){ int val_i = Dj[i] % 10; int def_i = Dj[i] / 10; int val_j = Dj[j] % 10; int def_j = Dj[j] / 10; if(val_i<val_j){ change(Dj,i,j); }else if(val_i==val_j){ if(def_i<def_j){ change(Dj,i,j); } } } } //把攻击升序排列 for (int i = 0; i < Aj.length; i++){ for(int j = i+1; j<Aj.length ;j++){ if(Aj[i]>Aj[j]){ change(Aj,i,j); } } } for (int i = 0; i < Dj.length; i++){ getFixedNum(Dj[i],Aj); } System.err.println("总价值:"+totalVal); } private static void change(int[] nums, int i, int j) { int num = nums[i]; nums[i] = nums[j]; nums[j] = num; } private static void getFixedNum(int Dj,int[] Aj){ boolean canSuc = false; //找到与防御值最接近的且不大于改值的攻击值 for(int i = Aj.length-1; i >=0; i--){ if(Aj[i]<=Dj/10 && Aj[i] != -1){ System.err.println("配对:"+Dj+"--"+Aj[i]); totalVal += Dj%10; Aj[i] = -1; //已用过的攻击牌置为-1 canSuc = true; break; } } //如果无法找到,则找到最大的攻击值 if(!canSuc){ for(int i = Aj.length-1; i >=0; i--){ if( Aj[i] != -1){ System.err.println("配对:"+Dj+"--"+Aj[i]); Aj[i] = -1; break; } } } }}result:配对:56--5配对:55--4配对:45--4配对:23--2配对:42--4配对:22--11配对:12--8配对:91--7配对:11--6总价值:22 Java求最大值编译之后出现找不到符号 MyEclipse 需要什么样的机器才能跑的欢 关于JFreeChart中柱状图使用纹理图片填充的解决办法 问两个hibernate主键的问题? 数组判断??? JAVA 帮助文档中的<E>、<?>、<T>代表什么呀 java 如何激活一个窗口为当前窗口? 怎么看一个ArrayList对象的容量? 如何用JDBC-ODBC连接其它机器上的数据库 请问各位,知道那有jbuilder 8的教材下吗! 怎么样判断ObjectInputStream是否读到文件末尾,文件长度未知,!!急!! 显示结果好奇怪???
先把 A 按攻击力非降序排好序
在把 B 一个个取出来用2分找到 A 中那个不能杀掉B且是最大的那个
如果这个位置目前还没匹配上 B, 那么把当前 B 与 A 匹配
如果这个位置有其他的 B 牌,
那么比较这2张B牌的价值,把价值大的与A匹配
价值小的那个B牌与当前A之前的其他A中的B牌比较(能不被当前A杀死的必然不能比之前的A杀死)
把价值小的那个B牌找到一个合适的位置与A匹配
//第一位表示防御值,第二位表示价值
private static int[] Dj = new int[] { 11, 23, 45, 22, 12, 55, 42, 56, 91 };
private static int[] Aj = new int[] { 11, 4, 2, 4, 5, 6, 7, 8, 4 };
private static int totalVal = 0;
public static void main(String args[]) {
//按价值-防御 逆序对原数组排序
for (int i = 0; i < Dj.length; i++){
for(int j = i+1; j<Dj.length ;j++){
int val_i = Dj[i] % 10;
int def_i = Dj[i] / 10;
int val_j = Dj[j] % 10;
int def_j = Dj[j] / 10;
if(val_i<val_j){
change(Dj,i,j);
}else if(val_i==val_j){
if(def_i<def_j){
change(Dj,i,j);
}
}
}
}
//把攻击升序排列
for (int i = 0; i < Aj.length; i++){
for(int j = i+1; j<Aj.length ;j++){
if(Aj[i]>Aj[j]){
change(Aj,i,j);
}
}
}
for (int i = 0; i < Dj.length; i++){
getFixedNum(Dj[i],Aj);
}
System.err.println("总价值:"+totalVal);
} private static void change(int[] nums, int i, int j) {
int num = nums[i];
nums[i] = nums[j];
nums[j] = num;
}
private static void getFixedNum(int Dj,int[] Aj){
boolean canSuc = false;
//找到与防御值最接近的且不大于改值的攻击值
for(int i = Aj.length-1; i >=0; i--){
if(Aj[i]<=Dj/10 && Aj[i] != -1){
System.err.println("配对:"+Dj+"--"+Aj[i]);
totalVal += Dj%10;
Aj[i] = -1; //已用过的攻击牌置为-1
canSuc = true;
break;
}
}
//如果无法找到,则找到最大的攻击值
if(!canSuc){
for(int i = Aj.length-1; i >=0; i--){
if( Aj[i] != -1){
System.err.println("配对:"+Dj+"--"+Aj[i]);
Aj[i] = -1;
break;
}
}
}
}
}result:
配对:56--5
配对:55--4
配对:45--4
配对:23--2
配对:42--4
配对:22--11
配对:12--8
配对:91--7
配对:11--6
总价值:22