VK-Cup2017 Wild Card Round 2

时间:2021-09-15 12:16:14

来自FallDream的博客,未经允许,请勿转载,谢谢。


Cf的Vkcup外卡赛2  上次round2和ditoly翻车了 所以只好来打打了  规则是给一道比较特殊的题目,你要找出较优的解

University Schedule/大学课程

有n个学生,m个教授,一周有6天,每天有7节课

告诉你每个学生这一周要和每个教授上多少节课 但是只有a个教室  也就是同一时间最多只能有a节课

定义学生和教授的疲劳度  假设一个学生/教授在一天上的第一节课是第x节,最后一节是第y节 那么它的疲劳度是(y-x+3)^2 如果没上课就没有疲劳度

你要合理的安排上课方案 使得教师和学生的疲劳度之和最小  n,m,a<=60   时间限制10s 有100个pretest

一开始写了一个贪心 让学生的课程平均分配   教授不管他 分数有点低...

很显然这样并不是特别优秀  而且浪费了非常多的时间 所以考虑换个做法

时间比较长 所以直接上了模拟退火  贪心之后 随机交换两个课程 另外贪心不一定优 所以加入一些空的课程一起交换

卡卡时 效果还可以 最后排到了第8位  实际上还有很多优化的空间 比如记下一天的最早最晚课程 答案 减少计算量等等

前几名写的算法不是很懂 (这种比赛的代码都奇奇怪怪 ) 还能找到几个退火的  但是感觉我和ditoly的代码最好看233

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#define Rep(a,b,c) for(int a=b;a<=c;++a)
using namespace std;
inline int read()
{
int x = ; char ch = getchar();
while(ch< '' || ch > '') ch = getchar();
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x;
} int n , m , a , Plan[][] , Class[][] , cnt= , Xs_ans[][] , Js_ans[][] , NewXs[][] , NewJs[][];
int ans , Xs[][][] , Js[][][] , Best , Best_Xs[][][];
struct Lesson{int xs,js,day,num;}L[];
inline int Sqr(int x){return x * x;} inline int Calc(int*Schedule)
{
int Early = , Last = ;
Rep(k , , )
if(Schedule[k])
(!Early) ? (Early = k) : , Last = k;
return Early ? Sqr(Last - Early + ) : ;
} void CalcAns()
{
ans = ;
Rep(i , , n)
Rep(j , , )
ans += (Xs_ans[i][j] = Calc( Xs[i][j] ));
Rep(i , , m)
Rep(j , , )
ans += (Js_ans[i][j] = Calc( Js[i][j] ));
} void Print()
{
printf("%d\n" , Best);
Rep(i , , n)
{
puts("");
Rep(j , , )
{
Rep(k , , )
printf("%d " , Best_Xs[i][k][j]);
puts("");
}
}
} void Copy()
{
Best = ans;
memcpy(Best_Xs , Xs , sizeof(Xs));
} inline int Ran()
{
return ((rand()<<)|rand()) % cnt + ;
} inline double Random()
{
return rand() / (double) RAND_MAX;
} bool check(int x , int y)
{
if( L[x].xs == L[y].xs)
{
if(L[x].js == L[y].js) return false;
if(Js[ L[x].js ][ L[y].day][ L[y].num ] || Js[ L[y].js ][ L[x].day][ L[x].num ]) return false;
return true;
}
if( L[x].js == L[y].js)
{
if(Xs[ L[x].xs ][ L[y].day ][ L[y].num ] || Xs[ L[y].xs ][ L[x].day ][ L[x].num ]) return false;
return true;
}
if(Xs[ L[x].xs ][ L[y].day ][ L[y].num ] || Js[ L[x].js ][ L[y].day][ L[y].num ]) return false;
if(Xs[ L[y].xs ][ L[x].day ][ L[x].num ] || Js[ L[y].js ][ L[x].day][ L[x].num ]) return false;
return true;
} int main()
{
srand( 413U );
n = read(); m = read(); a = read();
Rep(i , , n)
Rep(j , , m)
Plan[i][j] = read();
Rep(i , , n)
{
int j = , k = ;
for( ; ; )
{
for( ; !Plan[i][j] && j <= m ; ++j);
if( j > m ) break;
Rep(l , , )
if(Class[k][l] < a && !Xs[i][k][l] && !Js[j][k][l])
{
++Class[k][l];
Xs[i][k][l] = j;
Js[j][k][l] = i;
--Plan[i][j];
L[ ++cnt ] = (Lesson) {i , j , k , l};
break;
}
(++k == ) ? ( k = ) : ;
}
}
CalcAns();
Copy(); Rep(i , , )
Rep(j , , )
Rep(k , Class[i][j]+ , a)
L[++cnt] = (Lesson) { , , i , j}; double Temp = , delta = 0.99; time_t Beg = clock();
for( ; ; )
{
if(clock() - Beg > ) break;
Rep(it , , )
{
int x = Ran() , y = Ran();
if(check(x , y))
{
int Newans = ans;
Newans -= Xs_ans[ L[x].xs ][ L[x].day ];
Newans -= Xs_ans[ L[y].xs ][ L[x].day ];
Newans -= Js_ans[ L[x].js ][ L[x].day ];
Newans -= Js_ans[ L[y].js ][ L[x].day ];
if( L[x].day != L[y].day )
Newans -= Xs_ans[ L[x].xs ][ L[y].day ],
Newans -= Xs_ans[ L[y].xs ][ L[y].day ],
Newans -= Js_ans[ L[x].js ][ L[y].day ],
Newans -= Js_ans[ L[y].js ][ L[y].day ]; Xs[ L[x].xs ][ L[x].day ][ L[x].num ] = ;
Xs[ L[y].xs ][ L[y].day ][ L[y].num ] = ;
Js[ L[x].js ][ L[x].day ][ L[x].num ] = ;
Js[ L[y].js ][ L[y].day ][ L[y].num ] = ; Xs[ L[x].xs ][ L[y].day ][ L[y].num ] = L[x].js;
Xs[ L[y].xs ][ L[x].day ][ L[x].num ] = L[y].js;
Js[ L[x].js ][ L[y].day ][ L[y].num ] = L[x].xs;
Js[ L[y].js ][ L[x].day ][ L[x].num ] = L[y].xs; Newans += (NewXs[ L[x].xs ][ L[x].day ] = Calc(Xs[ L[x].xs ][ L[x].day ]));
Newans += (NewXs[ L[y].xs ][ L[x].day ] = Calc(Xs[ L[y].xs ][ L[x].day ]));
Newans += (NewJs[ L[x].js ][ L[x].day ] = Calc(Js[ L[x].js ][ L[x].day ]));
Newans += (NewJs[ L[y].js ][ L[x].day ] = Calc(Js[ L[y].js ][ L[x].day ]));
if( L[x].day != L[y].day )
Newans += (NewXs[ L[x].xs ][ L[y].day ] = Calc(Xs[ L[x].xs ][ L[y].day ])),
Newans += (NewXs[ L[y].xs ][ L[y].day ] = Calc(Xs[ L[y].xs ][ L[y].day ])),
Newans += (NewJs[ L[x].js ][ L[y].day ] = Calc(Js[ L[x].js ][ L[y].day ])),
Newans += (NewJs[ L[y].js ][ L[y].day ] = Calc(Js[ L[y].js ][ L[y].day ])); if(Newans < ans || Random() < exp((ans-Newans)/Temp))
{
if(Newans < ans) ans = Newans , Copy();
ans = Newans;
swap(L[x].day , L[y].day);
swap(L[x].num , L[y].num);
Xs_ans[ L[x].xs ][ L[x].day ] = NewXs[ L[x].xs ][ L[x].day ];
Xs_ans[ L[y].xs ][ L[x].day ] = NewXs[ L[y].xs ][ L[x].day ];
Js_ans[ L[x].js ][ L[x].day ] = NewJs[ L[x].js ][ L[x].day ];
Js_ans[ L[y].js ][ L[x].day ] = NewJs[ L[y].js ][ L[x].day ];
if( L[x].day != L[y].day )
Xs_ans[ L[x].xs ][ L[y].day ] = NewXs[ L[x].xs ][ L[y].day ],
Xs_ans[ L[y].xs ][ L[y].day ] = NewXs[ L[y].xs ][ L[y].day ],
Js_ans[ L[x].js ][ L[y].day ] = NewJs[ L[x].js ][ L[y].day ],
Js_ans[ L[y].js ][ L[y].day ] = NewJs[ L[y].js ][ L[y].day ];
}
else
{
Xs[ L[x].xs ][ L[y].day ][ L[y].num ] = ;
Xs[ L[y].xs ][ L[x].day ][ L[x].num ] = ;
Js[ L[x].js ][ L[y].day ][ L[y].num ] = ;
Js[ L[y].js ][ L[x].day ][ L[x].num ] = ; Xs[ L[x].xs ][ L[x].day ][ L[x].num ] = L[x].js;
Xs[ L[y].xs ][ L[y].day ][ L[y].num ] = L[y].js;
Js[ L[x].js ][ L[x].day ][ L[x].num ] = L[x].xs;
Js[ L[y].js ][ L[y].day ][ L[y].num ] = L[y].xs; }
}
}
Temp *= delta;
}
Print();
return ;
}