华为codecraft算法大赛—寻路

前言

最近实验室的师兄师姐们在热火朝天的笔试(都说难难难),我也要了些题来感受了一下,已然被虐的体无完肤。选择题考的内容涉及范围广,算法编程题对于没有刷题经验的我来说就更是难上加难了。看来有必要在学习工作之余学习学习算法以及计算机基础知识了。

翻了上半年参加华为codecraft算法大赛的代码,趁周末整理一下当时的思路以及回顾一下数据结构与算法。比赛前中期还保持不错的名次,一直维持在二十名左右以为稳稳三十二强了,结果后期突破不大,最后几天呼呼的被超过,真是太天真了。后来回想确实方法思路比较死板,一口咬定DFS+剪枝,没有去尝试新的算法如A*,模拟退火算法等,还有大赛群里分享说的动态规划、数模等。

比赛源码以及样例数据在我的github:
https://github.com/hczheng/2016Codecraft

赛题介绍

1 问题定义
给定一个带权重的有向图G=(V,E),V为顶点集,E为有向边集,每一条有向边均有一个权重。对于给定的顶点s、t,以及V的子集V’,寻找从s到t的不成环有向路径P,使得P经过V’中所有的顶点(对经过V’中节点的顺序不做要求)。
若不存在这样的有向路径P,则输出无解,程序运行时间越短,则视为结果越优;若存在这样的有向路径P,则输出所得到的路径,路径的权重越小,则视为结果越优,在输出路径权重一样的前提下,程序运行时间越短,则视为结果越优。
说明:
1)图中所有权重均为[1,20]内的整数;
2)任一有向边的起点不等于终点;
3)连接顶点A至顶点B的有向边可能超过一条,其权重可能一样,也可能不一样;
4)该有向图的顶点不会超过600个,每个顶点出度(以该点为起点的有向边的数量)不超过8;
5)V’中元素个数不超过50;
6)从s到t的不成环有向路径P是指,P为由一系列有向边组成的从s至t的有向连通路径,且不允许重复经过任一节点;
7)路径的权重是指所有组成该路径的所有有向边的权重之和。

2 输入与输出
输入文件格式
以两个.csv 文件(csv 是以逗号为分隔符的文本文件)给出输入数据,一个为图的数据(G),一个为需要计算的路径信息(s,t,V’)。文件每行以换行符(ASCII’\n’即0x0a)为结尾。

1)图的数据中,每一行包含如下的信息:
LinkID,SourceID,DestinationID,Cost
其中,LinkID 为该有向边的索引,SourceID 为该有向边的起始顶点的索引,DestinationID为该有向边的终止顶点的索引,Cost 为该有向边的权重。顶点与有向边的索引均从0 开始 编号(不一定连续,但用例保证索引不重复)。
2)路径信息中,只有一行如下数据:
SourceID,DestinationID,IncludingSet
其中,SourceID 为该路径的起点,DestinationID 为该路径的终点,IncludingSet 表示必须经过的顶点集合V’,其中不同的顶点索引之间用’|’分割。
输出文件格式
输出文件同样为一个.csv 文件。
1)如果该测试用例存在满足要求的有向路径P,则按P 经过的有向边顺序,依次输出有向边的索引,索引之间用’|’分割;
2)如果该测试用例不存在满足要求的有向路径P,则输出两个字符NA;
3)只允许输出最多一条有向路径。

3.简单用例说明

赛题思路

我当时第一反应就是最短路径算法,但是直接套用过来是肯定不行的,因为最短路径算法(dijkstra)是一层一层往外扩,然后利用贪心算法的思想得到每一层级的最优路径。二本赛题加了必过点的限制,因此需要对算法进行改造,为了能得到赛题结果,在一步步改造的过程中发现已经抛弃了贪心算法思想,最后渐渐的升级深度优先遍历(DFS)的基本思想,但是记录每一步遍历的顺序,方便回溯(在找到可行解的基础上还要考虑最优解)。随着比赛的进行,赛题数据复杂度的增加,回溯版DFS不能在有效的时间内得到最优解,甚至不能得到一个可行解。因此我又在该基础上增加了”剪枝”的思想,就是剪断一些出度较大的节点的路径,这样可以降低复杂度,并且能得到不错的结果,“剪枝”的尺度与位置其实是随机(缺乏科学性)的,由于是比赛,所以可以通过评分程序去修改算法拟合赛题数据。也是因为这种小聪明导致我这次比赛前中期效果不错,后期却非常乏力。这是应该吸取的教训,还是应该从算法本身的有效性入手,那样才会有真正的提高。

以下是输入数据以及输出结果样例



比赛源码

比赛要求的编译环境是Linux+gcc;为了方便调试,以下代码(已带详细注释)是Windows+Visual Stdio下的,有兴趣可以自行转换,也可以在以下地址下载提交版(包括华为官方提供的编译脚本)。

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fstream>
using namespace std;#define PRINT  printf
#define MAX_RECORD  100
#define MAX_LINE_LEN 4000
#define Error( Str )   FatalError( Str )
#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )
//邻接表读图,
//前面这些把图读进邻接表,
typedef struct ListNode *Position;//位置
typedef Position List;//链表
typedef struct Tbl *Table;//邻接表
typedef int ElementType;
typedef int Vertex;//顶点
typedef struct VertexTable *VerTable;//例子4个顶点
#define Infinity 65536 //各个顶点初始化
#define NotAVertex -1
#define nowstart 0//当前起点,初始化为0
#define NotFound -1//折半查找
#define LeftChild(i) (2*(i)+1)//堆排序
typedef struct StackRecord *Stack;
#define EmptyTOS -1//*************************************读文件********************************************//int read_file(char ** const buff, const unsigned int spec, const char * const filename)
{FILE *fp = fopen(filename, "r");if (fp == NULL){PRINT("Fail to open file %s, %s.\n", filename, strerror(errno));return 0;}PRINT("Open file %s OK.\n", filename);char line[MAX_LINE_LEN + 2];unsigned int cnt = 0;while ((cnt < spec) && !feof(fp)){line[0] = 0;fgets(line, MAX_LINE_LEN + 2, fp);if (line[0] == 0)   continue;buff[cnt] = (char *)malloc(MAX_LINE_LEN + 2);strncpy(buff[cnt], line, MAX_LINE_LEN + 2 - 1);buff[cnt][4001] = 0;cnt++;}fclose(fp);PRINT("There are %d lines in file %s.\n", cnt, filename);return cnt;
}//*************************************基本数据结构********************************************//struct StackRecord
{int Capacity;int TopOfStack;ElementType *Array;
};
////创建栈
Stack CreateStack(int MaxElements)
{Stack S;S = (struct StackRecord*)malloc(sizeof(struct StackRecord));if (S == NULL)FatalError("Out of space!!!");S->Array = (int*)malloc(sizeof(ElementType)*MaxElements);if (S->Array == NULL)FatalError("Out of space!!!");S->Capacity = MaxElements;S->TopOfStack = EmptyTOS;return S;
}
//出栈
void Pop(Stack S)
{if (S->TopOfStack == EmptyTOS)Error("Empty Stack");elseS->TopOfStack--;
}
//入栈
void Push(ElementType X, Stack S)
{if (S->TopOfStack == S->Capacity - 1)Error("Full stack");elseS->Array[++S->TopOfStack] = X;
}
//销毁栈
void DisposeStack(Stack S)
{if (S != NULL){free(S->Array);free(S);}
}
ElementType Top(Stack S)
{if (S->TopOfStack != EmptyTOS){return S->Array[S->TopOfStack];}else{Error("Empty Stack");return 0;}
}
//链表,每个存储了顶点Element,权重Cost,指向下一个的Next;
struct ListNode
{ElementType ELement;int Cost;int Priority;int Edge;Position Next;
};//0->1,1   Element=1,cost=1;//邻接表
struct Tbl
{int TableSize;List *TheLists;
};//顶点表
struct VertexTable
{int known;int Dist;Vertex Path;
};//*************************************邻接表初始化******************************************//Table InitializeTable(int TableSize)
{Table T;int i;T = (struct Tbl*)malloc(sizeof(struct Tbl));if (T == NULL)FatalError("Out of space!!!");T->TableSize = TableSize;T->TheLists = (struct ListNode**)malloc(sizeof(List)*T->TableSize);for (i = 0;i<T->TableSize;i++){T->TheLists[i] = (struct ListNode*)malloc(sizeof(struct ListNode));if (T->TheLists[i] == NULL)FatalError("Out of space!!!");elseT->TheLists[i]->Next = NULL;}return T;
}//*************************************链表插入********************************************//void Insert(int Edge, ElementType Pos, ElementType Key, ElementType Cost, ElementType Priority, Table T)
{Position NewCell;List L;NewCell = (struct ListNode*)malloc(sizeof(struct ListNode));if (NewCell == NULL)FatalError("Out of space!!!");else{L = T->TheLists[Pos];NewCell->Next = L->Next;NewCell->Edge = Edge;NewCell->ELement = Key;NewCell->Cost = Cost;NewCell->Priority = Priority;L->Next = NewCell;}
}//*************************************顶点表初始化*****************************************//VerTable InitialWeighted(Vertex Start, VerTable V, int NumVertex)//V为顶点集合,每隔顶点有三种标记
{int i;V = (struct VertexTable*)malloc(sizeof(struct VertexTable)*NumVertex);for (i = 0;i<NumVertex;i++){V[i].known = 0;V[i].Dist = 0;V[i].Path = NotAVertex;}V[Start].Dist = 0;return V;
}//*************************************二分查找********************************************//int BinarySearch(const ElementType A[], ElementType X, int N)
{int Low, Mid, High;Low = 0;High = N - 1;while (Low <= High){Mid = (Low + High) / 2;if (A[Mid]<X)Low = Mid + 1;elseif (A[Mid]>X)High = Mid - 1;elsereturn Mid;}return NotFound;
}void MakeEmpty(List L)
{Position P, Tmp;P = L->Next;L->Next = NULL;while (P != NULL){Tmp = P->Next;free(P);P = Tmp;}
}
void Disposable(Table T)
{int i;for (i = 0;i<T->TableSize;i++){MakeEmpty(T->TheLists[i]);}free(T->TheLists);free(T);
}//*************************************堆排序********************************************//void PercDown(ElementType A[], int i, int N)
{int Child;ElementType Tmp;for (Tmp = A[i];LeftChild(i)<N;i = Child){Child = LeftChild(i);if (Child != N - 1 && A[Child + 1]>A[Child])Child++;if (Tmp<A[Child])A[i] = A[Child];elsebreak;}A[i] = Tmp;
}
void Swap(int *a, int *b)
{int temp;temp = *a;*a = *b;*b = temp;
}
void Heapsort(ElementType A[], int N)
{int i;for (i = N / 2;i >= 0;i--)PercDown(A, i, N);for (i = N - 1;i>0;i--){Swap(&A[0], &A[i]);PercDown(A, 0, i);}
}//*************************************打印路径********************************************//void PrintPath(Vertex Ver, VerTable V, int C[])
{if (V[Ver].Path != NotAVertex){PrintPath(V[Ver].Path, V, C);printf("->");}printf("%d", C[Ver]);
}//************************************输出边编号*******************************************//int find_route(int stop, Table T, VerTable V)
{Position Tmp;int result = -1;Tmp = T->TheLists[V[stop].Path]->Next;//while (Tmp != NULL){if (Tmp->ELement == stop) { result = Tmp->Edge;break; }Tmp = Tmp->Next;}return result;
}///*************************************重复边处理****************************************//Position FindPrevious(ElementType X, List L)
{Position P;P = L;while (P->Next != NULL && P->Next->ELement != X)P = P->Next;return P;
}
int IsLast(Position P, List L)
{return P->Next == NULL;
}void Delete(ElementType X, List L)
{Position P, TmpCell;P = FindPrevious(X, L);if (!IsLast(P, L))  /* Assumption of header use */{                      /* X is found; delete it */TmpCell = P->Next;P->Next = TmpCell->Next;  /* Bypass deleted cell */free(TmpCell);}
}
Position Find(ElementType X, List L)
{Position P;P = L->Next;while (P != NULL && P->ELement != X)P = P->Next;return P;
}///*******************************/自定义查找下一顶点的算法*************************************//int find_start(VerTable V, Table T, ElementType demand[], int start_now, int known_p, int end, Stack S, int N)
{//传入的参数分别为:顶点表(konwn,dis,path)、优先点集、当前遍历起点//返回值为下一个起点索引TempV,以及特征点入栈Position tmp;int min = Infinity;//普通点最小权值int min_sp = Infinity;//优先点最小权值int count_sp = 0;//优先点计数(用于判断特征点)int count_normal = 0;//普通点计数int normal[8] = { 0 };//普通点数组(暂存)int special[8] = { 0 };//优先点数组(暂存)Vertex TempV = -1;//开始标记int flag = 0;//终点标记//TMP = T->TheLists[start_now];tmp = T->TheLists[start_now]->Next;while (tmp != NULL) //0->3->1->NULL  还有邻接点且未到达过{if (V[tmp->ELement].known != 1) {if (tmp->Priority == 1)//如果该顶点是优先点{count_sp++;//当前层级优先点数+1if (tmp->Cost < min_sp) //当前点权值更小{if (count_sp > 1){special[count_sp - 2] = TempV;V[TempV].Dist = 0;}min_sp = tmp->Cost;//更新min_sp                   TempV = tmp->ELement;//返回值V[TempV].Dist = V[start_now].Dist + tmp->Cost;}else{if (count_sp > 1){special[count_sp - 2] = tmp->ELement;;}}}else if (tmp->ELement == end)//如果该顶点是终点{flag = 1;//表明这一轮有终点,但暂时不作处理V[end].Dist = V[start_now].Dist + tmp->Cost;V[end].Path = start_now;}else //如果该顶点是普通点{count_normal++;//普通点计数normal[count_normal - 1] = tmp->ELement;//普通点暂存if (count_sp == 0 && tmp->Cost < min)//(1.有普通点没有终点没有优先点2.有普通点有终点没有优先点){min = tmp->Cost;//更新minV[TempV].Dist = 0;TempV = tmp->ELement;//返回值  V[TempV].Dist = V[start_now].Dist + tmp->Cost;}}}tmp = tmp->Next;}///////////*************************LOOK***************************///////////////if (count_sp == 0) //假如没有优先点,则把多余的普通点全部入栈{for (int i = 0;i < count_normal;i++){if (TempV != normal[i]){Push(normal[i], S);Push(start_now, S);//V[normal[i]].Path = start_now;}}//普通点分支入栈      }else//当优先点数>=1时{if (count_sp == 1)//假如刚好只有一个优先点,那么普通点入栈,并赋值path{for (int i = 0;i < count_normal;i++) { Push(normal[i], S); Push(start_now, S); }//V[normal[i]].Path = start_now;}else//当优先点数大于1时,普通点先全部入栈,然后多余的优先点入栈{for (int i = 0;i < count_normal;i++) { Push(normal[i], S); Push(start_now, S); } //V[normal[i]].Path = start_now;for (int i = 0;i < count_sp - 1;i++) { Push(special[i], S);Push(start_now, S); }//V[special[i]].Path = start_now;}}if (flag == 1 && known_p == N)//已到终点,且这一层没有优先点了,就要判断是否已经结束(优先点已全部在路径中){TempV = 10000; //10000结束标志,到达终点且所有的优先点已在路径中}if (TempV == -1) { TempV = -start_now; if (start_now == 0) { TempV = -1000; } }//返回停止点(带负号,方便处理)if (TempV != 10000 && TempV >= 0) { V[TempV].Path = start_now; }return TempV;//返回下一起点索引
}//**************************************核心查找算法********************************************//int DF(VerTable V, Table T, ElementType demand[], Stack S, int N, int start_now, int end, unsigned short *result,int big)
{//Vertex Ver, W;//顶点索引Position Tmp;//int end = 5;//假定一个终点int startone=start_now ;//存起点int known_p = 0;//记录已到过的优先点int flag = 0;//遍历过优先点标记int min_dist = 10000;int ok = 0;for (;;){if (start_now == 10000)//当前起点为10000,查找成功{flag++;//迭代次数if (min_dist > V[end].Dist){int tmp = end;int count = 0;while (tmp != startone){result[count] = find_route(tmp, T, V);count++;ok = count;tmp = V[tmp].Path;}min_dist = V[end].Dist;}else V[end].Dist = min_dist; if (S->TopOfStack == -1||flag>10) break;printf("flag:%d\n",flag);           //if (big>7&&big<30)break;//if (big>150 && big<200&&flag>7)break;//if (big>200 && big<250 && flag>3)break;if (big>250&&flag>0)break;int pass = Top(S);//获得特征点索引 0->1->3                 Pop(S);//出栈start_now = Top(S);//将当前起点改为栈顶元素        int stop = V[end].Path;//继续回溯while (stop != pass){V[stop].known = 0;if (BinarySearch(demand, stop, N) >= 0) { known_p--; }stop = V[stop].Path;}Pop(S);//出栈 /*if (S->TopOfStack != -1) {if (big> 150&&big<200) { Pop(S);Pop(S); }//边数在if (big> 200 && big<250) { Pop(S);Pop(S);Pop(S);Pop(S); }//边数在200-250,一次剪断两条边if (big> 250) { Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);Pop(S); }//边数大于250,一次剪断三条边*///剪枝操作V[start_now].Path = pass;//出栈起点路径信息Tmp = T->TheLists[pass]->Next;while (Tmp != NULL){if (Tmp->ELement == start_now) { V[start_now].Dist = V[pass].Dist + Tmp->Cost; }Tmp = Tmp->Next;}}       if (start_now < 0 && S->TopOfStack == -1) break; //栈空,则返回无解if (start_now <0)//回头{int stop = -start_now;//停止点if (start_now == -1000) { stop = 0; }//0为停止点的情况int pass = Top(S);//获得特征点索引 0->1->3                 Pop(S);//出栈//printf("%d出栈:\n", pass);start_now = Top(S);//将当前起点改为栈顶元素            while (stop != pass){V[stop].known = 0;if (BinarySearch(demand, stop, N) >= 0) { known_p--; }//printf("%d回撤:\n", stop);stop = V[stop].Path;//V[stop].Path = NotAVertex;}Pop(S);//出栈 //printf("%d出栈:\n", start_now);if (S->TopOfStack != -1) {//if (big>150 && big < 200) { Pop(S);Pop(S);}//边数在150-200之间,一次剪断一条边if (big> 100&&big<250) { Pop(S);Pop(S);Pop(S);Pop(S); }//边数在200-250,一次剪断两条边if (big> 250) { Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);}//边数大于250,一次剪断三条边}//剪枝操作V[start_now].Path = pass;//出栈起点路径信息Tmp = T->TheLists[pass]->Next;while (Tmp != NULL){if (Tmp->ELement == start_now) { V[start_now].Dist = V[pass].Dist + Tmp->Cost; }Tmp = Tmp->Next;}}V[start_now].known = 1;//将当前起点标记为已知if (BinarySearch(demand, start_now, N) >= 0) { known_p++; }//记录到达的优先点数start_now = find_start(V, T, demand, start_now, known_p, end, S, N);//按自定义方法找下一个起点printf("当前点:%d\n",start_now);}return ok;
}//**************************************调用算法********************************************//void search_route(char *graph[5000], int edge_num, char *condition)//字符串数组(topo),行数,字符串(demand)
{Table T = InitializeTable(600);//顶点VerTable V = NULL;Stack S = CreateStack(1000);//创建栈(存分支点)unsigned short result[100] = { -1 };//示例中的一个解 const int n = edge_num;int  N, start_now, end, demand[100] = { -1 }, test[400][4] = { 0 };char *save_ptr, *line;//存剩余的for (int i = 0;i<n;i++)//test初始化{char *hello = graph[i];char *p, *token;int j = 0;for (p = hello; ; p = NULL, j++){token = strtok_s(p, ",", &save_ptr);if (NULL == token)   break;test[i][j] = atoi(token);}}start_now = atoi(strtok_s(condition, ",", &save_ptr));//起点printf("start_now=%d \n", start_now);end = atoi(strtok_s(NULL, ",", &save_ptr));//终点printf("end=%d \n", end);line = strtok_s(NULL, ",", &save_ptr);//优先点字符串printf("special_line=%s \n", line);char *get, *token;save_ptr = NULL;int d_count = 0;for (get = line; ; get = NULL, d_count++){token = strtok_s(get, "|", &save_ptr);if (NULL == token)   break;demand[d_count] = atoi(token);// printf("demand[%d]=%d \n",d_count,demand[d_count]);}N = d_count;int Sort[400 * 2] = { -1 }, Max, *C, p = 0, Stemp, Etemp, *Fdemand;for (int i = 0; i < n; i++){Sort[2 * i] = test[i][1];Sort[2 * i + 1] = test[i][2];}//把起点和终点包含的点都算进来Heapsort(Sort, n * 2);//对顶点进行排序Max = Sort[2 * n - 1];C = (int*)malloc(sizeof(int)*(Max + 1));if (NULL == C){FatalError("Out of space!!!");}for (int i = 0;i<2 * n;i++){if (Sort[i] != Sort[i + 1]){C[p] = Sort[i];p++;}}printf("edge_num=%d \n", n);printf("point_num=%d \n", p);printf("special_num=%d \n", N);Fdemand = (int*)malloc(sizeof(int)*(N));;for (int i = 0;i<N;i++){Stemp = BinarySearch(C, demand[i], p);Fdemand[i] = Stemp;}Heapsort(Fdemand, N);Position Pos,L;/*for (int j = 0;j<n;j++)//邻接表插入{Stemp = BinarySearch(C, test[j][1], p);Etemp = BinarySearch(C, test[j][2], p);if (BinarySearch(Fdemand, Etemp, N) >= 0){Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);//start,stop,cost,List,把3必过点插入T->TheLists[Stemp]->ELement++;//有几个优先级的点}else{Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);//start,stop,cost,List,把3必过点插入T->TheLists[Stemp]->ELement++;//有几个优先级的点}}*/
////////////////////////////////////////////////////for (int j = 0;j<n;j++){Stemp = BinarySearch(C, test[j][1], p);Etemp = BinarySearch(C, test[j][2], p);if (BinarySearch(Fdemand, Etemp, N) >= 0){L = T->TheLists[Stemp];Pos = Find(Etemp, L);if (NULL == Pos){Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);//start,stop,cost,List,把3必过点插入T->TheLists[Stemp]->ELement++;//有几个优先级的点}else{if (Pos->Cost > test[j][3]){Delete(Pos->ELement, L);T->TheLists[Stemp]->ELement--;//有几个优先级的点Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);T->TheLists[Stemp]->ELement++;//有几个优先级的点}}}else{L = T->TheLists[Stemp];Pos = Find(Etemp, L);if (NULL == Pos){Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);T->TheLists[Stemp]->ELement++;//有几个优先级的点}else{if (Pos->Cost > test[j][3]){Delete(Pos->ELement, L);T->TheLists[Stemp]->ELement--;//有几个优先级的点Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);//start,stop,cost,List,把3必过点插入T->TheLists[Stemp]->ELement++;//有几个优先级的点}}}}////////////////////////////////////////////////////start_now = BinarySearch(C, start_now, p);end = BinarySearch(C, end, p);V = InitialWeighted(0, V, n);int route = DF(V, T, Fdemand, S, N, start_now, end, result,n);//最短路径D算法     int tmp = end;int result_count = route;//解的个数if (route == 0) { printf("NA\n"); }else{/*if (N>=16) {result_count =0;while (tmp != start_now){result[result_count] = find_route(tmp, T, V);result_count++;tmp = V[tmp].Path;}}*/PrintPath(end, V, C);printf(" COST=%4d\n", V[end].Dist);for (int i = result_count - 1;i >= 0;i--){printf("%d | ", result[i]);//record_result(result[i]);}printf("\n");}Disposable(T);DisposeStack(S);free(V);free(C);free(Fdemand);//record_result(result[i]);
}int main()
{char *topo[5000];int edge_num;char *demand;int demand_num;edge_num = read_file(topo, 5000, "topo.csv");demand_num = read_file(&demand, 1, "demand.csv");search_route(topo, edge_num, demand);getchar();return 0;
}

华为codecraft算法大赛---寻路相关推荐

  1. 华为2019算法大赛CTR预估数据探索

    华为2019算法大赛CTR预估数据探索 训练集 时间信息 siteId(媒体Id) slotId(广告位Id) netType(网络连接类型) id类信息 测试集 媒体id 网络型号 测试集与训练集分 ...

  2. 华为digix算法大赛2020机器学习赛道-ctr预估初赛/决赛rank1

    华为digix算法大赛2020机器学习赛道-ctr预估初赛/决赛rank1 写在前面 1.比赛成绩 2.基础方案 2.1.赛题理解 2.2.特征工程 2.3.算法实现 3.冷启动探索 3.1.数据分析 ...

  3. 报名 | 搜狐×清华:第三届内容识别算法大赛,比武招新两不误!

    2019年4月8日,第三届搜狐校园算法大赛正式开赛,同期面向参赛选手开放竞赛结果提交.本次比赛联合了清华大学等机构共同组织,面向全球范围内的全日制学生. [组织方]搜狐.清华大学 [奖金]¥75000 ...

  4. 名校大厂 AI 高手云集,芒果 TV 音视频算法大赛硕果累累

    东京奥运会已正式开幕,最新的IT技术也在进入奥运赛场. 本届奥运会引入的 AI 辅助打分,扮演了"助理裁判"的角色.这项技术可以追踪选手动作并实时转换为三维立体图像,再由系统根据图 ...

  5. 千亿企业的真实业务思考,名校大厂高手同台 PK,“马栏山杯”国际音视频算法大赛来袭!...

    在刚结束的计算机视觉顶级学术会议CVPR 2021上,涌现了多种优秀的计算机视觉AI算法解决方案. 其中最佳论文奖为<GIRAFFE:Representing Scenes as Composi ...

  6. 【赠书】腾讯广告算法大赛冠军、Kaggle Grandmaster倾力打造,涵盖Kaggle、阿里天池等赛题...

    随着互联网时代的到来,以及计算机硬件性能的提升,人工智能在近几年可以说是得到了爆发式的增长.互联网时代带来了大量的信息,这些信息是名副其实的大数据.另外,性能极佳的硬件也使得计算机的计算能力大大增强, ...

  7. 腾讯广告算法大赛冠军、Kaggle Grandmaster倾力打造,涵盖Kaggle、阿里天池等赛题...

    随着互联网时代的到来,以及计算机硬件性能的提升,人工智能在近几年可以说是得到了爆发式的增长.互联网时代带来了大量的信息,这些信息是名副其实的大数据.另外,性能极佳的硬件也使得计算机的计算能力大大增强, ...

  8. 高校计算机大赛华为云,学子风采丨我校学生荣获华为云人工智能大赛无人车挑战杯总决赛一等奖...

    原标题:学子风采丨我校学生荣获华为云人工智能大赛无人车挑战杯总决赛一等奖 2020年8月14日,华为云人工智能大赛无人车挑战杯总决赛举行,我校学子龙羿辰,张衍杨,李哲远,葛以勒,王为之与交大附中国际部 ...

  9. 【国庆赠书】腾讯广告算法大赛冠军、Kaggle Grandmaster倾力打造,涵盖Kaggle、阿里天池等赛题...

    值此国庆佳节,给大家赠书啦!祝大家假期快乐!(可在文末参与活动) 随着互联网时代的到来,以及计算机硬件性能的提升,人工智能在近几年可以说是得到了爆发式的增长.互联网时代带来了大量的信息,这些信息是名副 ...

最新文章

  1. select2 4.0.8 + , 动态搜索数据
  2. Linux 网络配置命令:ip、ss
  3. 【并查集】【最小生成树】【贪心】给水(jzoj 2015)
  4. android sp wp实例,android sp wp详解
  5. Python与机器视觉(x)下雨啦,图片模拟雨天效果
  6. 95-140-114-源码-transform-算子project
  7. python之路 《四》 字典
  8. 面试时企业最看中你什么能力?
  9. win10 uwp 重启软件
  10. 基于dde-top-panel+tint2+plank+conky的Deepin(深度)桌面美化
  11. 互联网共享图书馆+自习室商业计划书
  12. 《深入理解Windows操作系统》笔记5
  13. U3D连接Steamworks SDK制作成就系统
  14. matlab数字调制蒙特卡洛仿真,AWGN信道下数字通信系统的蒙特卡洛仿真(基于matlab)...
  15. 一 Django模型层简介
  16. python中shuffle是什么意思_python中shuffle()方法的功能详解
  17. 8款高质量小程序推荐:(工具类、电影类、阅读类)
  18. Ajax发送的put请求过程
  19. 4002 构造数组(可重复组合数问题--隔板法)
  20. 解决:ERROR kuhl m_privilege simple: Rtiadjustprivilege (20) c0000061

热门文章

  1. 用友后台数据库如何彻底删除
  2. django问题详解
  3. Linux/Ubuntu下ffmpeg安装教程
  4. Interview preparation-- manager
  5. 塔式,机架式,刀片式区别
  6. 电商营销如何玩转粉丝运营?教你3种技巧
  7. mysql的text与tinytext,MySQL中的VARCHAR(255)和TINYTEXT字符串类型有什么区别?
  8. Java输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。
  9. MrDoc——语雀的开源替代品,可私有部署、无用户限制、数据完全掌控
  10. Scapy 网络数据包构建