各問題で自分がどう考え、どのようなコードを書いたかをここに記します。
今回は、ローカルでテストケースを入力して出力を生成する形式なので、
その気になれば(コンテスト時間内なら)いくらでも計算できます。
A: Random Trip
50000頂点もあるので、一見全てのスタート/ゴールの組を考えて計算するのはかなり難しそうです。
しかし、よく考えると各頂点をスタート/ゴールとして選ぶ確率が0~100、合計100の整数で表されるので、
スタート/ゴールとして選ばれる可能性のある頂点はそれぞれ高々100個しかないということに気付きます。
よって、全探索できます。
よく考えずにダイクストラ法のライブラリを貼り付けましたが、よく考えたら素直に深さ優先探索でよかったようです。
ソースコード
► スポイラーを表示
#include
#include
#include
#define DIJKSTRA_MAX_NODE 50000
#define DIJKSTRA_MAX_EDGE 100000
typedef struct {
int from,to;
int cost;
} dijkstra_edge_t;
typedef struct {
int node;
int cost;
} dijkstra_node_t;
int dijkstra_edge_num;
dijkstra_edge_t dijkstra_edge[DIJKSTRA_MAX_EDGE];
int dijkstra_node_edge[DIJKSTRA_MAX_NODE][2];
int dijkstra_queue_num;
dijkstra_node_t dijkstra_queue[DIJKSTRA_MAX_EDGE+1];
int dijkstra_cost[DIJKSTRA_MAX_NODE];
char dijkstra_visited[DIJKSTRA_MAX_NODE];
int dijkstra_comp(const void* x,const void* y) {
const dijkstra_edge_t* a=(const dijkstra_edge_t*)x;
const dijkstra_edge_t* b=(const dijkstra_edge_t*)y;
if((a->from)>(b->from))return 1;
if((a->from)from))return -1;
if((a->to)>(b->to))return 1;
if((a->to)to))return -1;
return 0;
}
void dijkstra_queue_adjust(int pos) {
int min=pos;
if(pos*2+1dijkstra_queue[pos*2+1].cost)
min=pos*2+1;
if(pos*2+2dijkstra_queue[pos*2+2].cost)
min=pos*2+2;
if(min!=pos) {
dijkstra_node_t temp;
temp=dijkstra_queue[min];
dijkstra_queue[min]=dijkstra_queue[pos];
dijkstra_queue[pos]=temp;
dijkstra_queue_adjust(min);
} else if(pos>0)dijkstra_queue_adjust((pos-1)/2);
}
void dijkstra_queue_push(int node,int cost) {
dijkstra_node_t topush;
topush.node=node;topush.cost=cost;
dijkstra_queue[dijkstra_queue_num++]=topush;
dijkstra_queue_adjust(dijkstra_queue_num-1);
}
dijkstra_node_t dijkstra_queue_pop(void) {
dijkstra_node_t result=dijkstra_queue[0];
if(dijkstra_queue_num>0) {
dijkstra_queue[0]=dijkstra_queue[--dijkstra_queue_num];
dijkstra_queue_adjust(0);
}
return result;
}
void dijkstra_init(void) {
dijkstra_edge_num=0;
}
void dijkstra_addedge(int from,int to,int cost) {
dijkstra_edge[dijkstra_edge_num].from=from;
dijkstra_edge[dijkstra_edge_num].to=to;
dijkstra_edge[dijkstra_edge_num].cost=cost;
dijkstra_edge_num++;
}
void dijkstra_setup(void) {
int i;
int prev;
qsort(dijkstra_edge,dijkstra_edge_num,
sizeof(dijkstra_edge_t),dijkstra_comp);
prev=0;
memset(dijkstra_node_edge,0,sizeof(dijkstra_node_edge));
dijkstra_node_edge[0][0]=0;
for(i=0;i0) {
dijkstra_node_t nownode=dijkstra_queue_pop();
if(!dijkstra_visited[nownode.node]) {
dijkstra_visited[nownode.node]=1;
dijkstra_cost[nownode.node]=nownode.cost;
for(i=dijkstra_node_edge[nownode.node][0];
inownode.cost+dijkstra_edge[i].cost)) {
dijkstra_queue_push(
dijkstra_edge[i].to,
nownode.cost+dijkstra_edge[i].cost
);
dijkstra_cost[dijkstra_edge[i].to]=nownode.cost+dijkstra_edge[i].cost;
}
}
}
}
return dijkstra_cost[to];
}
typedef struct {
int id;
int p;
} candidate_t;
int main(void) {
int T,caseCount;
scanf("%d",&T);
for(caseCount=0;caseCount0) {
if(s_cand_num>=100) {
error=1;
puts("too many start candidates");
break;
}
s_cand[s_cand_num].id=i;
s_cand[s_cand_num].p=P;
s_cand_num++;
}
if(Q>0) {
if(g_cand_num>=100) {
error=1;
puts("too many goal candidates");
break;
}
g_cand[g_cand_num].id=i;
g_cand[g_cand_num].p=Q;
g_cand_num++;
}
}
if(error)continue;
dijkstra_setup();
for(i=0;i1の時ですが、上の方法をそれぞれのコインについて部分的に計算すれば良さそうです。
1円玉が2個のコインに接している位置は方程式を解けば求まりそうですが、
時間終了が迫っていてめんどくさかったので二分探索しました。
ソースコード
[spoil][code=c]#include
#include
double getangle(int a,int b) {
double left=0;
double right=4*atan(1); /* pi */
double mid=0;
double x,y,r;
for(;;) {
mid=(left+right)/2.0;
x=-a-(a+1)*cos(mid);
y=(a+1)*sin(mid);
r=(b-x)*(b-x)+y*y;
if(r>(b+1)*(b+1)) {
if(left==mid)break;
left=mid;
} else {
if(right==mid)break;
right=mid;
}
}
return mid;
}
double getangle2(int a,int b) {
return (4*atan(1))-getangle(b,a);
}
int main(void) {
double pi=4*atan(1);
int T,caseCount;
scanf("%d",&T);
for(caseCount=0;caseCount
#include
int alen,blen;
int a[2000000+1024];
int b[2000000+1024];
int memo[1024][1024];
int search(int apos,int bpos) {
int result=0,nowresult;
if(apos>alen || bpos>blen)return 0;
if(memo[apos][bpos]>0)return memo[apos][bpos]-1;
nowresult=search(apos,bpos+1);
if(nowresult>result)result=nowresult;
nowresult=search(apos+1,bpos);
if(nowresult>result)result=nowresult;
nowresult=search(apos+1,bpos+1);
if(a[apos]==b[bpos])nowresult++;
if(nowresult>result)result=nowresult;
memo[apos][bpos]=result+1;
return result;
}
int main(void) {
int T,caseCount;
scanf("%d",&T);
for(caseCount=0;caseCount1000 || N>1000) {
puts("give up");
continue;
}
alen=M;
blen=N;
/* generate the sequence */
a[0]=P;
for(i=1;i
#include
int M,N,K;
char map[32][32];
short memo[24][2=M)return status==0?1:0;
if(memo[pos][status]>0)return memo[pos][status]-1;
imax=(2
const int Flist[27][3]={
{1,1,1},
{2,1,1},
{3,1,1},
{1,2,1},
{2,2,1},
{3,2,1},
{1,3,1},
{2,3,1},
{3,3,1}, /* I */
{1,1,2},
{2,1,2},
{3,1,2},
{1,2,2},
{2,2,2},
{3,2,2},
{1,3,2},
{2,3,2},
{3,3,2}, /* R */
{1,1,3},
{2,1,3},
{3,1,3},
{1,2,3},
{2,2,3},
{3,2,3},
{1,3,3},
{2,3,3}, /* Z */
{3,3,3}
};
int F(char id,int x) {
return Flist[id-'A'][x-1];
}
int searchF(int one,int two,int three) {
int i;
for(i=0;ib){t=a;a=b;b=t;}
y=Fren(a-1,b,x);
r=(int)(((long long)K*r+L+i+y)%M);
if(i==nextQuery) {
printf("%d",y);
nextQuery
#include
#define DIVIDE_NUM 10000000
double func(double t,int A,int B,double w) {
return (1.0-pow(A,-t))*(pow(B,-t)-pow(B,-(t+w)));
}
int main(void) {
int T,caseCount;
int M,N,A,B;
double result;
int i;
const double end=100;
const double w=end/DIVIDE_NUM;
scanf("%d",&T);
for(caseCount=0;caseCount
#include
static int barMax;
static int nowBar;
void initProgress(int max) {
barMax=max;
nowBar=0;
fputs("--------20--------40--------60--------80-------100 [%]\n",stderr);
}
void updateProgress(int now) {
int nowPos=(int)((long long)now*50/barMax);
if(nowPos>50)nowPos=50;
for(;nowBar1)result++;
return result;
}
int qsc(const void* x,const void* y) {
int a=*((const int*)x);
int b=*((const int*)y);
if(a>b)return 1;
if(a0?'+':(g<0?'-':'0'));
}
nowQuery++;
}
updateProgress(i);
}
for(i=0;i<N;i++) {
printf("%c\n",queryResponse[i]);
}
return 0;
}
人力で読みましょう。といってもそのまま読むのは辛いので、適当な単語で検索します。
ソースコード(として提出したもの)
► スポイラーを表示
solved by hands
read the statement by text editor
search english words:
first
calc
sequence
number
element
which
great
test
H1
2. 4136- outputabsolutedifferencebetweenfirstintegerandlastinteger
5. 2238- whatsfirstelementplusnthelement
8. 7379- findsumoffirsttwonumbersinsequence
11. 8144- whatslastintegermultipliedbyfirstintegerinsequence
14. 1170- computeproductoffirsttwoelements
17. 6777- printsumofallnumbersinsequences
20. 8115- calculatesumoflasttwointegersinsequence
23. 721- whatisfirstnumbersubtractedbysecondnumber
26. 3348- determineproductoflasttwonumbers
29. 3833- findfirstintegertimeslastintegerinsequence
H2
2. 5465- outputsmallestintegerinsequence
5. 9781- whichelementinsequenceisfourthsmallest
8. 2338- whatelementhasexactlyfivenumbersbiggerthanit
11. 7784- whatsseventhlargestelementfromsequence
14. 1267- outputbiggestoneofgivennumbers
17. 2825- whichnumberinsequencehasexactlytwootherslessthanitself
20. 6581- findsixthsmallestelementinsequence
23. 1921- printeighthbiggestofgivennumbers
26. 4712- printfourthlargestelementfrominput
29. 7444- findsecondgreatestintegerinsequence
32. 8873- whichislargestelementfrominput
35. 9702- whichintegerhasexactlythreeotherintegerssmallerthanit
38. 873- insequencewhichelementhasexactlyoneothersmallernumber
41. 1700- printeighthsmallestelementfrominput
44. 3826- findsixthgreatestamonggivenintegers
47. 2673- whichisgreatestintegerinsequence
50. 6614- whatisthirdbiggestofgivennumbers
53. 7284- justsayhelloforthistestcaseinlowercase
56. 7500- outputfifthlargestelementofsequence
59. 2407- printsmallestoneofgivennumbers