A - 咕咕东的奇遇
思路:
这一题没有太多难度,就是模拟实际的转盘,运用好模运算,注意好细节即可。
代码:
#include <stdio.h>
char input[20000];
char table[27];
int main()
{
scanf("%s",input);
for(int i=97;i<123;i++)
{
table[i-97]=i;
}
int word=0;
int needle=0;
int count=0;
while(input[word]!=0)
{
for(int j=needle;j<26+needle;j++)
{
if(table[j%26]==input[word])
{
if(j-needle>13)
{
count=count+26-(j-needle);
needle=j%26;
break;
}
else
{
count=count+j-needle;
needle=j%26;
break;
}
}
}
word++;
}
printf("%d",count);
}
B - 咕咕东想吃饭
思路:
这一题在做题过程中我并未拿到满分。在比赛中我对于这题的思路是采用dfs对所有购买策略进行暴力枚举,比赛中我对dfs进行了部分剪枝,但是没有使用记忆化搜索,最后跑出了70分。因此我觉得我的思路没有问题,只是算法不够优化。但我在补题的时候发现哪怕我把记忆化搜索做了,进行更多的剪枝操作,也还是无法通过后面几个测试点。于是我和同学交流了一下,发现这题原来不需要用dfs,而是观察规律,然后使用贪心算法,直接给出相应的购买策略即可。这里的购买策略为:若可以不买1个的,就全买2个的。反映到具体情况中来就是:从第一天开始,若该天需要奇数个,则让第二天的所需个数减一,若需要偶数个,则不需变动。然后直到最后一天,若最后一天所需个数为奇数,则不存在相应方案,若为偶数,则存在。
代码:
#include <stdio.h>
int num[150000];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&num[i]);
}
int remain=0;
for(int i=0;i<n-1;i++)
{
num[i]=num[i]-remain;
if(num[i]%2==0)
{
remain=0;
}
else
{
remain=1;
}
}
if((num[n-1]-remain)%2!=0)
{
printf("NO");
}
else
{
printf("YES");
}
}
C - 可怕的宇宙射线
思路:
这题的思路非常明了,就是用bfs在二维数组内模拟过程。要注意的点一个是方向的表示,一个是如何模拟射线的运动过程,还有一个就是要想到在一个狭小的空间内射线分裂30次即2的30次方束不同射线,这种时候应该有大量的重复,所以应该要使用记忆化搜索。这里我采用了结构体来表示射线分裂的那个节点,用于模拟过程。因此记忆化搜索时也只需记录结构体即可。
代码:
#include <iostream>
#include <queue>
#include <map>
using namespace std;
int mark[501][501];
int disx[8]={-1,-1,0,1,1,1,0,-1};
int disy[8]={0,1,1,1,0,-1,-1,-1};
struct arrow
{
int x;
int y;
int direction;
int split;
bool operator <(const arrow &a) const
{
if(x==a.x)
if(y==a.y)
if(direction==a.direction)
return split<a.split;
else
return direction<a.direction;
else
return y<a.y;
else
return x<a.x;
}
};
map<arrow,bool> vis;
queue<arrow> q;
int num[35];
map<int,int> map1;
map<int,int> map2;
int main()
{
map1[0]=1;map1[1]=2;map1[2]=3;map1[3]=4;map1[4]=5;map1[5]=6;map1[6]=7;map1[7]=0;
map2[0]=7;map2[1]=0;map2[2]=1;map2[3]=2;map2[4]=3;map2[5]=4;map2[6]=5;map2[7]=6;
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>num[i];
arrow first;
first.x=250;first.y=250;first.direction=0;first.split=0;
for(int j=num[0]-1;j>=0;j--)
mark[250+j][250]=1;
q.push(first);
while(!q.empty())
{
arrow tmp=q.front();
q.pop();
if(vis[tmp]==1)
continue;
else
vis[tmp]=1;
int d=tmp.direction;
int tx=tmp.x;
int ty=tmp.y;
int ts=tmp.split;
if(ts==n-1)
continue;
for(int j=0;j<num[ts+1];j++)
{
mark[tx+(j+1)*disx[map1[d]]][ty+(j+1)*disy[map1[d]]]=1;
mark[tx+(j+1)*disx[map2[d]]][ty+(j+1)*disy[map2[d]]]=1;
}
arrow tmp1;arrow tmp2;
tmp1.direction=map1[d];tmp1.split=ts+1;tmp1.x=tx+num[ts+1]*disx[map1[d]];tmp1.y=ty+num[ts+1]*disy[map1[d]];
tmp2.direction=map2[d];tmp2.split=ts+1;tmp2.x=tx+num[ts+1]*disx[map2[d]];tmp2.y=ty+num[ts+1]*disy[map2[d]];
q.push(tmp1);
q.push(tmp2);
}
int count=0;
for(int i=0;i<501;i++)
{
for(int j=0;j<501;j++)
{
if(mark[i][j]==1)
count++;
}
}
cout<<count;
}