VK-Cup2017 Wild Card Round 2
来自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 = 0; char ch = getchar(); while(ch< '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x; } int n , m , a , Plan[66][66] , Class[66][66] , cnt=0 , Xs_ans[66][7] , Js_ans[66][7] , NewXs[66][7] , NewJs[66][7]; int ans , Xs[66][7][8] , Js[66][7][8] , Best , Best_Xs[66][7][8]; struct Lesson{int xs,js,day,num;}L[100001]; inline int Sqr(int x){return x * x;} inline int Calc(int*Schedule) { int Early = 0 , Last = 0; Rep(k ,1 , 7) if(Schedule[k]) (!Early) ? (Early = k) : 0 , Last = k; return Early ? Sqr(Last - Early + 3) : 0; } void CalcAns() { ans = 0; Rep(i , 1 , n) Rep(j , 1 , 6) ans += (Xs_ans[i][j] = Calc( Xs[i][j] )); Rep(i , 1 , m) Rep(j , 1 , 6) ans += (Js_ans[i][j] = Calc( Js[i][j] )); } void Print() { printf("%d\n" , Best); Rep(i , 1 , n) { puts(""); Rep(j , 1 , 7) { Rep(k , 1 , 6) printf("%d " , Best_Xs[i][k][j]); puts(""); } } } void Copy() { Best = ans; memcpy(Best_Xs , Xs , sizeof(Xs)); } inline int Ran() { return ((rand()<<15)|rand()) % cnt + 1; } 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 , 1 , n) Rep(j , 1 , m) Plan[i][j] = read(); Rep(i , 1 , n) { int j = 1 , k = 1; for( ; ; ) { for( ; !Plan[i][j] && j <= m ; ++j); if( j > m ) break; Rep(l , 1 , 7) 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 == 7) ? ( k = 1 ) : 0; } } CalcAns(); Copy(); Rep(i , 1 , 6) Rep(j , 1 , 7) Rep(k , Class[i][j]+1 , a) L[++cnt] = (Lesson) {0 , 0 , i , j}; double Temp = 100 , delta = 0.99; time_t Beg = clock(); for( ; ; ) { if(clock() - Beg > 9950 ) break; Rep(it , 1 , 40000) { 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 ] = 0; Xs[ L[y].xs ][ L[y].day ][ L[y].num ] = 0; Js[ L[x].js ][ L[x].day ][ L[x].num ] = 0; Js[ L[y].js ][ L[y].day ][ L[y].num ] = 0; 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 ] = 0; Xs[ L[y].xs ][ L[x].day ][ L[x].num ] = 0; Js[ L[x].js ][ L[y].day ][ L[y].num ] = 0; Js[ L[y].js ][ L[x].day ][ L[x].num ] = 0; 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 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream