高分悬赏!!!随机数问题。

snowrain_2008 2009-04-28 08:57:59
这里有2个数组,
int x[]={1908,4218,5767,6416,8637,15614,8948,
17723,13698,9867,35085,16705,20595,50504,53688,
23548,25477,20345,18336,24645,68070,10552,10024,
17810,13219,14645,20105,13903,24035,20474,43073};

int y[]={91009,14869,15459,18354,19054,22573,33566,19850,
26725,22593,15877,34075,23895,24990,59862,48301,
11417,13657,10059,5466,18403,36273,8326,14760,
8573,5079,4144,6197,1524,2042,670};
要求目标数组rain[31][31]里面随机生成数值。并且
1。。。。。。。。。。。。。。rain数组里面第一行只有一个元素,第二行有2个元素,第三行有3个元素。以此类推
2。。。。。。。。。。。。。。随机产生的值第一行总和等于x[0],第二行总和等于x[1],第三行总和等于x[2],以此类推。
3。。。。。。。。。。。。。。同时要保证第一列的总和等于y[0],第二列总和等于y[1],第三列总和等于y[2],以此类推。
4.。。。。。。。。。。。。。。随机值要在200以上15000以下。

以上皆为要求。特此悬赏120分。。。不好意思,没权限发120分,只能发100分。
先可以简单看出rani数组有2个值是给定了的。就是rain[0][0]肯定是1908,rain[31][31]肯定是670.
...全文
199 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
hc0120 2009-05-03
  • 打赏
  • 举报
回复
神呐!
yangc_83 2009-04-30
  • 打赏
  • 举报
回复
人才啊!
jinxfei 2009-04-30
  • 打赏
  • 举报
回复
不容易,终于做出来了:


import java.util.Random;

public class SuijiShuzu {
private static int randMax = 15000, randMin = 200;
private static int arrayDimension = 31;

private static int x[]={1910,4218,5767,6416,8637,15614,8948,
17723,13698,9867,35086,16705,20596,50504,53689,
23548,25478,20346,18336,24645,68070,10552,10024,
17810,13219,14645,20105,13904,24035,20474,43073};

private static int y[]={91009,14869,15459,18354,19054,22573,33566,19850,
26725,22593,15877,34075,23895,24990,59862,48301,
11417,13657,10059,5466,18403,36273,8326,14760,
8573,5079,4144,6197,1524,2042,670};

public static void main(String[] args) {
System.out.println("sum of array x:"+sum(x)+", sum of array y:"+sum(y));
Random rand = new Random(System.currentTimeMillis());
int[][] rain = new int[arrayDimension][arrayDimension];
// 逆向思维啊
// 第一步,既然最小值是200,则,先按要求给可能有数的点都填上200再说
//满足第一点约束:rain数组里面第一行只有一个元素,第二行有2个元素,第三行有3个元素。以此类推
for (int i = 0; i < arrayDimension; i++) {
for (int j = 0; j <= i; j++) {
rain[i][j] = randMin;
}
}
// 第二步,把已经放到数组中的200,按行、列之和从x、y两个数组中减去
for (int i = 0; i < arrayDimension; i++) {
x[i] -= (i + 1) * randMin;
y[arrayDimension - i - 1] -= (i + 1) * randMin;
}

//第三步,把X数组中的每一个元素x[i],按照对应的y[j]/sum[y]的比例,平均分布到该行的各数据点,
//在分布的过程中,增加一定的随机性(正负50,可以调)
for (int i = 0; i < arrayDimension; i++) {
int currentX=x[i];
int sumY=sum(y,0,i+1);
for (int j = 0; j <= i; j++) {
long share=(long)(1L*currentX*y[j])/(long)sumY;
int nextRand=rand.nextInt(100)-50;
long preResult=rain[i][j]+share+nextRand;
if (preResult>randMin && preResult<randMax){
share+=nextRand;
}
rain[i][j] += share;
x[i]-=share;
y[j]-=share;
}
}

// 第四步,我们把X数组中剩下的值,分发到对应行的随机列上,分发到某列的同时,我们在这个列对应的y数组中,也减去1,
// 经过这一步,可以保证X数组全部为0,也就是,每行的和 符合要求。
int count=0;
for (int i = x.length-1; i >=0; i--) {
while (x[i] != 0) {
// 这里随机产生的是一个坐标值x,如果rain[i][x]<randMax,则rain[i][x]++
int nextRand = rand.nextInt(i+1);
if (rain[i][nextRand] < randMax && rain[i][nextRand]>randMin) {
if (x[i]>0){
rain[i][nextRand]++;
x[i]--;
y[nextRand]--;
}else{
rain[i][nextRand]--;
x[i]++;
y[nextRand]++;
}

}
}
}
//最后一步,由于行已经符合要求,但列可能不符合要求,
//所以我们要根据y数组中当前值(可能有负数)来做列迁移(挖高补低),一直到y数组中也全部为0
for(int i=0; i<y.length;i++){
while (y[i]>0){//如果当前的列和值小于0,则说明当前列还需要做行调整
int negIndex=findNegative(y);//首先找到一个列和值为负数的下表,就在这两列之间调整

if (negIndex<0){
System.out.println("终于完事儿了!");
break;
}else{
int adjustRowIndex=negIndex;
if (y[negIndex]+y[i]>=0){
rain[adjustRowIndex][negIndex]+=y[negIndex];
rain[adjustRowIndex][i]-=y[negIndex];
y[i]+=y[negIndex];
y[negIndex]=0;

}else{
rain[adjustRowIndex][negIndex]-=y[i];
rain[adjustRowIndex][i]+=y[i];
y[negIndex]+=y[i];
y[i]=0;
}
}
}
}
System.out.println("随机数组:");
dump(rain);
System.out.println("sum of array x:"+sum(x)+", sum of array y:"+sum(y));
}

private static int findNegative(int[] array){
for(int i=0; i<array.length;i++){
if (array[i]<0){
return i;
}
}
return -1;
}
private static void dump(int[][] array) {
for (int i = 0; i < array.length; i++) {
dump(array[i]);
}
}

private static void dump(int[] array) {
for (int j = 0; j < array.length; j++) {
System.out.print(array[j] + "\t");
}
System.out.println();
}
private static int sum(int[] array){
int sum=0;
for(int i=0; i<array.length;i++){
sum+=array[i];
}
return sum;
}
private static int sum(int[] array,int start, int end){
int sum=0;
for(int i=start;i<end;i++){
sum+=array[i];
}
return sum;
}
private static int min(int a, int b){
return a<b?a:b;
}
}


jinxfei 2009-04-29
  • 打赏
  • 举报
回复
先可以简单看出rani数组有2个值是给定了的。就是rain[0][0]肯定是1908,rain[31][31]肯定是670.

红色部分结论不对,没有规定第一行的一个数必须在0,0位置。
yesvery 2009-04-29
  • 打赏
  • 举报
回复
这是一个31元1次方程,如果有解,应该是唯一的解。用随机数来凑,效率太低。
可惜这题肯定无解,因为x[]中的各元素之和与y[]里的各元素之和 不相等(差8)
请楼主检查一下,数据错在哪里。
注:x[]中的各元素之和应该等于rain[][]中的各元素之和
y[]中的各元素之和也应该等于rain[][]中的各元素之和
yesvery 2009-04-29
  • 打赏
  • 举报
回复
再做思考后,发现我原先的想法有误。
这是一个496元1次不定方程,其解N多。
不知楼主为何不用解方程的思路,而一定要用随机数去凑。
这个问题的确很有意思,可惜太忙,无暇关顾。
这个问题对楼主真的很重要吗?
jinxfei 2009-04-29
  • 打赏
  • 举报
回复
晕,
我计算了一下x数组和y数组的和:
sum of array x:637634, sum of array y:637642

不相等,所以这个题目不可能完成。

楼主是不是抄错了数字?
snowrain_2008 2009-04-29
  • 打赏
  • 举报
回复
yesvery是牛人,说的一点没错.数据的确是错了.所以特地数据从新改了下.
x[]={1910,4218,5767,6416,8637,15614,8948,
17723,13698,9867,35086,16705,20596,50504,53689,
23548,25478,20346,18336,24645,68070,10552,10024,
17810,13219,14645,20105,13904,24035,20474,43073};

y[]={91009,14869,15459,18354,19054,22573,33566,19850,
26725,22593,15877,34075,23895,24990,59862,48301,
11417,13657,10059,5466,18403,36273,8326,14760,
8573,5079,4144,6197,1524,2042,670};
pathuang68 2009-04-28
  • 打赏
  • 举报
回复
snowrain_2008 2009-04-28
  • 打赏
  • 举报
回复
可以重复的。8楼的说的不错,最后的数值是rain[30][30]=670;
这个问题想了许久都没想出。望诸位高手给个解答。
yesvery 2009-04-28
  • 打赏
  • 举报
回复
算法思路,供楼主参考
1 创建数组rain[30][30]

2 为 rain 赋值,具体方法:
rain[0][0]=1908,其余的rain[0][x]=0
rain[1][0]=随机数,rain[1][1]=随机数,其余的rain[1][x]=0
rain[2][0]=随机数,rain[2][1]=随机数,rain[2][2]=随机数,其余的rain[2][x]=0
rain[3][0]=随机数,rain[3][1]=随机数,rain[3][2]=随机数,rain[3][3]=随机数,其余的rain[3][x]=0
依此类推,直到rain[30][x]全部赋以随机数

3 编制两个循环,分别将数组的各数据按横向以及纵向相加,与x[]以及y[]的相应元素相比较:
若有任何不相等,就退出循环,重新回到第二步,再来一遍。
若无不等,则数组 rain 中的各元素数值就是所需结果
yesvery 2009-04-28
  • 打赏
  • 举报
回复
算法思路,供楼主参考
1 创建数组rain[30][30]

2 为 rain 赋值,具体方法:
rain[0][0]=1908,其余的rain[0][x]=0
rain[1][0]=随机数,rain[1][1]=随机数,其余的rain[1][x]=0
rain[2][0]=随机数,rain[2][1]=随机数,rain[2][2]=随机数,其余的rain[2][x]=0
rain[3][0]=随机数,rain[3][1]=随机数,rain[3][2]=随机数,rain[3][3]=随机数,其余的rain[3][x]=0
依此类推,直到rain[30][x]全部赋以随机数

3 编制两个循环,分别将数组的各数据按横向以及纵向相加,与x[]以及y[]的相应元素相比较:
若有任何不相等,就退出循环,重新回到第二步,再来一遍。
若无不等,则数组 rain 中的各元素数值就是所需结果
yesvery 2009-04-28
  • 打赏
  • 举报
回复
最后的那个数 应该是rain[30][30]吧?
huangan0301 2009-04-28
  • 打赏
  • 举报
回复
顶~
yesvery 2009-04-28
  • 打赏
  • 举报
回复
感觉不是随机数的问题,而是求解线性方程的问题
jeans_zh 2009-04-28
  • 打赏
  • 举报
回复
看到数组我就晕了!
JarodYv 2009-04-28
  • 打赏
  • 举报
回复
rain中的数能否重复?
qybao 2009-04-28
  • 打赏
  • 举报
回复
这道题,因为有随机生成,所以难度比较大
首先通过回溯法求出所有解,然后再从所有解中随机取一组
这个跟以前的一道题类似,大概如下的形式,具体忘了
a1 b1 c1 ? e1
? b2 c2 d1 ?
a3 ? ? ? e3
? ? c4 ? ?
然后每一行的?有条件限制
当时用回溯法实现过,如果只求一个解,很快的,要求所有解,跑了半个多小时都没跑完
如果LZ这个显得更复杂,还是31x31(当然最终不是31x31,而是像99乘法表一样)
现在没环境,先mark一下了


znwuyan318 2009-04-28
  • 打赏
  • 举报
回复
感觉像是在做数学题哈
xuezhanliang6886 2009-04-28
  • 打赏
  • 举报
回复
顶顶顶!!

13,100

社区成员

发帖
与我相关
我的任务
社区描述
Java J2ME
社区管理员
  • J2ME社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧