最优数字分配策略

题目:

最优数字分配策略
比赛题目条件:
假设有2500个数据存储单元,形成为50*50的正方形矩阵。每个数据存储单元允许存储2~5个整数,整数范围为1~30,每个整数使用次数不限。
 
50*50数据存储单元如下表形式:

1-1 1-2 1-3 1-4 …

2-1 2-2 2-3 2-4 …

3-1 3-2 3-3 3-4 …

4-1 4-2 4-3 4-4 …

… … … … …

其中1-1、1-2等表示存储单元在矩阵中的行列位置,也可以将其作为存储单元的名称。
 
比赛题目要求:

  • 将1~30的整数按各存储单元的整数个数要求,分配到各数据存储单元中。未按要求分配整数,比赛无成绩,直接出局;
  • 每个存储单元内的整数不能相同且不能相邻。如:1和2、2和2、2和3不能出现在同一个存储单元中。如果违反规则,按下述罚则处理:针对每个存储单元都统计一遍,出现一次相同,结果累加100违约分;出现一次相邻,结果累加50违约分;
  • 每个存储单元与相邻的存储单元内的整数不能相同且不能相邻。如:第2-2存储单元内的整数与第1-1、1-2、1-3、2-1、2-3、3-1、3-2、3-3存储单元内的整数不能相同且不能相邻。如果违反规则,按下述罚则处理:针对每个存储单元都统计一遍,出现一次相同,结果累加20违约分;出现一次相邻,结果累加10违约分;
  • 每个存储单元与相邻存储单元的相邻存储单元内的整数不能相同。如:第2-2存储单元内的整数与第1-4、2-4、3-4、4-1、4-2、4-3、4-4存储单元内的整数不能相同。如果违反规则,按下述罚则处理:针对每个存储单元都统计一遍,出现一次相同,结果累加1违约分;

 

 

1.每次计算对边界的控制比较繁琐,所以在外围多了2圈,这样便于code。

2.初始化外界为-1,空间内部为0,这样就方便了算分。

3.有很多重复的代码……尽量放在函数内重复使用,这样看起来也很舒服,嘿嘿。

4.为了避免重复计算,引入了flag标记被计算的单元。

5.将空间旋转90 180 270度和计算3次的结果一样,就直接重复计算了3次。(可能是我方法不对,也请前辈指正)

 

#pragma once
#define N 50
#define S 30
int cnt = 0;
typedef struct {
int a[5] = { -1,-1,-1,-1,-1 };
int testData;
}Unit;
Unit Space[N + 5][N + 5];
Unit tempSpace[N + 5][N + 5][10]; //保存每次计算产生的结果,0-9


//flag用来标记已经计算过的位置,初始:0代表未计算过,1代表计算过
int flag[N + 5][N + 5] = { 0 };


typedef struct {
int grade = 0;
int c_100 = 0;
int c_50 = 0;
int c_20 = 0;
int c_10 = 0;
int c_1 = 0;
int c_0 = 0;
}Arr;
Arr sign[S + 1];
Arr temp[10]; //tempSpace -> grade


int finally_grade = 0;
typedef struct {
int a_100 = 0;
int a_50 = 0;
int a_20 = 0;
int a_10 = 0;
int a_1 = 0;
}Cnt;
Cnt grade_cnt;

//主要的计算填单元格的函数:

//找出违约分最小的编号,返回要填入的那个值
int select_min()
{
//从sign中选出grade最小的数
int min = 1;
int t; //临时记录最小的sign[].grade

t = sign[1].grade;
for (int j = 1; j <= S; j++) /2
{
if (sign[j].grade <= t)
{
t = sign[j].grade;
min = j;
}
}




return min;
}


//计算
void calculate()
{
printf("正在计算……\n");
int i, j;
for (i = 2; i <= N+1; i++)  //反向测试测试标记//
{
for (j = 2; j <= N+1; j++) //反向测试测试标记//
{


//initSign();
for (int x = 0; x < Space[j][i].testData; x++) //反向测试标记//
{
initSign();
for (int y = 1; y <= S; y++) //从1-30填数,并计算每一个的违约分
{

Space[j][i].a[x] = y;
calculate_grade(j, i, x, y); //违约分存在sign[y]中
}
Space[j][i].a[x] = select_min();//找出sign中最小违约分的标记,并赋给这个空
}




}
}


cnt++;
//printf("第 %d 次计算完成!\n",cnt);
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值