请教各位一个高难的算法题,有重谢!

zzq_xaut 2008-01-20 08:03:30
请教各位一个高难的算法题:
例如有3行4列的非负整数矩阵,如下:
1 2 3 4
5 6 7 8
9 10 11 12
约束条件是:排列的结果中必须保证——1在2的前面、2在3的前面等等;5在6的前面、6在7的前面等等;9至12依次类推;而且1、5、9谁在前谁在后不受任何限制。
这样,对该矩阵进行某种特定的复杂运算后得到多个排列(可能有重复的),比如其中的一个排列如下:
1 5 2 6 9 3 10 7 11 8 12 4
现在问题是:如何对此排列实施随机性的变换,使其仍然符合上述约束条件并且和原来的排列不一样???

我的QQ 121622170,如能解决必有重谢!
...全文
485 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zzq_xaut 2008-02-23
  • 打赏
  • 举报
回复
HW121,谢谢!貌似你的回答最接近我的要求,给你分!
ai_3621 2008-02-09
  • 打赏
  • 举报
回复
这个easy啊。

计算下总计多少个排列数字,编号,

假设总数为x,

随机输入一个数字,把该数字加上+一个随即数字,

把当前编号+随机数字编号的排列输出即可。


HW121 2008-01-30
  • 打赏
  • 举报
回复
使用STL中next_permutation很容易解决这个问题:
1、用一个临时排列,每行元素值等于行标;
2、将临时排列中的相同行号按每列的顺序排列即可。
实施随机性的变换,可以将临时排列调用next_permutation, prev_permutation后再步骤2,可得出下一个或上一个排列
遍历,可以从最小开始,调用next_permutation生成下一个临时,换算成符合上述约束条件,直至走遍所有的排列。
#include   <stdio.h> 
#include <algorithm>
using namespace std;

void main()
{
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int row[12], count = 0;
for(int r = 0; r < 3; r++)
for(int i = 0; i < 4; i++)
row[r*4+i] = r;
do {
int i, b[3];
for(i = b[0] = b[1] = b[2] = 0; i < 12; i++)
printf("%2d ", a[ row[i] ][ b[row[i]]++ ] );
printf("\n");
count++;
}while( next_permutation(row, row + 12) );
printf("count=%d\n",count);
}
zzq_xaut 2008-01-23
  • 打赏
  • 举报
回复
chinaunix上有人这么说:
其实可以建立一个偏序集。那种在这个偏序集中无法比较大小的元素,或者不在这个偏序集上的元素可以互相交换,不影响对规则的遵守。
规则,1在2之前,1在3之前
1 大
/ \
2 3 小
2和3可以互相交换



如果偏序集上的元素小于等于10个,那么选择任意两个不在偏序集上的元素交换即可。
否则的话,只要偏序集不是链,那么在任何一个分叉点,取该分叉点的两个最小上界或者最小下界,让其交换即可。

另外,如果该偏序集的图并非连通图的话,在不同的连通子图上取点,交换也可。

<introduction of algorithms>第22章里<topological sort>描述的就是这种问题.

将那些有先后关系的结点按父子关系排成一棵树, 最后的问题就成了树或森林的遍历。
liuzongqiang 2008-01-23
  • 打赏
  • 举报
回复
明白其中难点了,一会就帮你弄出来.
liuzongqiang 2008-01-23
  • 打赏
  • 举报
回复
随机性的变换什么意思啊?
我原来给你的代码稍微修改一下你想怎么变就怎么变
jmulxg 2008-01-22
  • 打赏
  • 举报
回复
原序列1,5,2,6,9,3,10,7,11,8,12,4

1、随机产生位置种子(0-11),比如位置3,则选择数字'6'

2、'6'属于第二组(闭区间[5,8]),因此随机左右移动'6',满足'6'的位置在'5','7'之间即可;若随机到数字'1','5','9','4','8','12'需要特殊的处理,
比如'1',则可以移动的区间为 开始到'2'之前,而'4'可以移动的区间'3'之后到结束

3、重复步骤(2)N(N=1,2,3..)次即可
HW121 2008-01-22
  • 打赏
  • 举报
回复
更正:
如果要再已有的排列对几个数字实施随机性的变换,可以先找到这几个数字所在位置的连续区间,存到数组x[xn]中,
将这个区间数字按行分类A1[n1]、A2[n2]、A3[n3],
在xn个位置随机选择n1个位置, 将A1数据由小到大放入x对应位置,继续在剩下随机选择n2个位置将A2数据由小到大放入x对应位置,至结束。

最简单情况:
如果要交换一个数字c,找到数字c位置,向后移动出现非自己行数据d,从d开始与前一个位置交换,至原c的位置;这就是向后移动数字c的下一个位置。


HW121 2008-01-22
  • 打赏
  • 举报
回复
我看这是一个排列组合问题,给一个遍历的方法:
1、在12个位置选择四个位置有C(4,12)种组合,将第一行数据由小到大放入四个位置。
2、在剩下的8个位置中选择四个位置,将第二行数据由小到大放入四个位置。
3、在剩下的四个位置,将第第三行数据由小到大放入四个位置。
总共有C(4,12)×C(4,8)×C(4,4) = 34965可能

如果要再已有的排列对几个数字实施随机性的变换,可以先找到这几个数字所在位置,存到数组x[xn]中,
这些数字按行分类A1[n1]、A2[n2]、A3[n3],
在xn个位置随机选择n1个位置, 将A1数据由小到大放入x对应位置,继续在剩下随机选择n2个位置将A2数据由小到大放入x对应位置,至结束。


liuzongqiang 2008-01-22
  • 打赏
  • 举报
回复
还不给分啊.^_^
guzhilei1986 2008-01-21
  • 打赏
  • 举报
回复
期待中……
zzq_xaut 2008-01-21
  • 打赏
  • 举报
回复
liuzongqiang,非常感谢你的回复!但是问题没有解决,生成符合约束条件的排列倒是不难,而我需要解决的问题是:

如果已有一个符合约束的排列(用一维整型数组存储表示),例如:1 5 2 6 9 3 10 7 11 8 12 4,现在要求对此排列实施随机性的变换(比如随机交换2或3个数字等),使得变换出的排列既符合约束条件又和原来的不一样。
zzq_xaut 2008-01-21
  • 打赏
  • 举报
回复
非常感谢!等我测试好了就给分!!!
liuzongqiang 2008-01-20
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define COLUMN 4
#define LINE 3
void pump(int line,int column,int out[])
{
int r,t=column*line,i=t;int *a;
a=(int*)malloc(sizeof(int)*t);
while(--i>=0)
{
if(i%column==0)a[i]=0;
else a[i]=i-1;
}
i=0;/*other use*/
int j=0;
int c;
while(true)
{
if(line<1)break;
c=-1;
r=rand()%line+1;
while(r-->0)
{
c+=column;
while(a[c]==-1)c+=column;
}
c=c-column+1;
while(a[c]==-1)c++;
out[j++]=c;
a[c]=-1;
if((c+1)%column==0)line--;
else a[c]=-1;
}

}

int main()
{
srand((unsigned int)time(NULL));
int a[]={
1,2,3,4,
5,6,7,8,
9,10,11,12
};
int out[12];
pump(3,4,out);
for(int i=0;i<COLUMN*LINE;i++)
{
printf("%d ",a[out[i]]);
if(!((i+1)%COLUMN))printf("\n");
}
}

vc6编译通过.
pump实现你所要的功能,main()测试
每次执行打印随机打印一个序列.
main中数组a的元素可以随便改,但是个个数应该等于调用时column*line
有问题联系我.
liuzongqiang 2008-01-20
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void pump(int line,int column,int out[])
{
int r,t=column*line,i=t;int *a;
a=(int*)malloc(sizeof(int)*t);
while(--i>=0)
{
if(i%column==0)a[i]=0;
else a[i]=i-1;
}
i=0;/*other use*/
int j=0;
int c;
while(true)
{
if(line<1)break;
c=-1;
r=rand()%line+1;
while(r-->0)
{
c+=column;
while(a[c]==-1)c+=column;
}
c=c-column+1;
while(a[c]==-1)c++;
out[j++]=c;
a[c]=-1;
if((c+1)%column==0)line--;
else a[c]=-1;
}

}

int main()
{
srand((unsigned int)time(NULL));
int a[]={
1,2,3,4,
5,6,7,8,
9,10,11,12
};
int out[12];
pump(3,4,out);
for(int i=0;i<12;i++)
{
printf("%d ",a[out[i]]);
if(!((i+1)%4))printf("\n");
}
}



vc6编译通过.
pump实现你所要的功能,main()测试
每次执行打印随机打印一个序列.
main中数组a的元素可以随便改,但是个个数应该等于调用时column*line
有问题联系我.
内容概要:本文详细介绍了基于无刷直流电机的电子机械制动执行器的MATLAB/Simulink仿真模型,重点构建并深入分析了其非线性动力学特性。该模型深度融合了无刷直流电机的电磁动力学与制动执行机构的机械传动动力学,通过引入高精度的Stribeck摩擦模型,有效提升了对系统在启动、停止及低速运行等工况下复杂动静态摩擦行为的模拟能力,从而实现了对整个执行器系统动态响应特性、控制性能及瞬态过程的高保真仿真,为下一代线控刹车(Brake-by-Wire)系统的研发、控制算法验证与优化提供了强大的数字化设计与验证平台。; 适合人群:具备一定电机控制理论、汽车电子工程、自动化或机电一体化背景的研究生、高校科研人员及从事电驱动系统、汽车底盘控制系统开发的工程师。; 使用场景及目标:①用于电子机械制动(EMB)系统总体方案的设计、可行性验证与动态性能评估;②作为开发与在环测试(HIL/SIL)先进控制器(如高鲁棒性PID、滑模变结构控制、模型预测控制MPC等)的核心仿真平台;③深入研究电机与精密丝杠等机械部件之间的强耦合效应,以及非线性摩擦对系统控制精度、响应延迟和稳态误差的影响机制。; 阅读建议:学习者应熟练掌握MATLAB/Simulink软件操作,并具备电机学、经典与现代控制理论、机械动力学等相关基础知识,建议在理解模型架构的基础上,通过调整关键参数(如摩擦系数、转动惯量、传动比)和施加不同的指令信号与负载扰动,系统性地探究系统各环节的动态响应规律,进而进行模型的二次开发与优化。

33,025

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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