今天的题解写晚了,因为光光是改程序调程序就改到了23:20分这个样子,所以说今天的题解可能会略为的潦草和语无伦次请见谅!
1.英语
怎么说呢…这道题的题意和英语完全不相干啊!我也不知道为什么它叫英语=。=
题意:把石子分成N堆,每次可以取出一个或几个石子(不可以不取),每次取完石子之后可以选择将余下的部分石子分给其他堆(可以不移动),给出石子的数量,请输出是否有先手必胜的策略。
考试的时候我很清楚的记得吴大爷在培训的day9讲过这样一道拓展题,但我干脆就忘了正解是什么了,于是我就写了一份NIM一般游戏的代码(既不用分石子的NIM游戏),居然骗到了90分我非常的开心啊。但是这道题的正解也是非常好想的。
第一个if:对于每一个只有一堆石子的状态,都是一个先手必胜的状态。
第二个if:对于每一个只有两堆石子的状态,同一般NIM游戏的思考方式,异或和为0时先手必败,否则先手必胜。
第三部分:对于每一堆石子,若有一堆石子的数目不为1则先手必胜。
/*
2016.8.5 CHN
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int n;
int x,y;
bool win=0;
int main()
{
freopen("english.in","r",stdin);
freopen("english.out","w",stdout);
while(scanf("%d",&n)==1)
{
win=0;
if(n==1)
{
scanf("%d",&x);
printf("YES\n");
continue;
}
if(n==2)
{
scanf("%d%d",&x,&y);
if(x==y) printf("NO\n");
else printf("YES\n");
continue;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x!=1) win=true;
}
if(win) printf("YES\n");
else
{
if(!n&1) printf("NO\n");
else printf("YES\n");
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
2.化学
这道鬼畜的题让我差点就调了一宿过去,本来以为今天晚上是写不了题解了,没想到今天晚上居然精力比较充沛,于是就打算趁热打铁赶紧来一发题解了。
题意:一个由5个田字格拼成十字形组成的棋盘,给出点N并以此给出这N个点的坐标,每次移动棋子的时候必须要满足一下几个条件才能移动:1.每次移动能且仅能向上下左右四个方向移动两个格子。2.每次移动的目标点点目前不能有棋子(棋子不可以累加) 3.每次移动的时候必须是跳过去的而不是走过去的,就是说移动还要满足初始点与目标点的中电必须要有一个棋子。移动后被跨过的棋子被删去。
分析:分析题意我们可以知道:由于每次必须且仅能删除一个点,所以说要走到最后的状态既图中只有一个点的情况时必定只移动了n-1次棋子。我选择了比较好写的dfs进行搜索,因为我们已知深度和决策,可以限制dfs的深度。
易错点:每进行一步操作的时候我们有很多需要改变的东西:改变此次被移动的棋子的坐标,改变存储棋子位置的图,同时记录每一步的横纵坐标和进行的操作的种类。同时还要注意的是,i轴的增加是Down,i轴的减少是Up,j轴的增加为Right,j轴的减少为Left。
优化:这道题如果直接dfs的话肯定没有广搜要优,如何降低其时间复杂度呢?由于在棋盘边缘的点,或者在图块边缘的点进行移动很可能出现无解的情况,所以我们可以从内向外搜,既从图块的内部向外部拓展,这样可以更快更直接的找到可达到的最优解。
(题主实在懒得打注释了,已经是后半夜了,见谅!)
/*
2016.8.5CHN
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
struct point
{
int x,y;
}p[40];
int ans=2147483600;
int a[8][8];
int n;
int tot=0;
int st[500005];
int poi[500005];
int mox[500005];
int moy[500005];
int w[3][5]=
{
0,0,0,0,0,
0,2,-2,0,0,
0,0,0,2,-2,
};
bool cmp(point l,point ll)
{
return abs(l.x-l.y)<abs(ll.x-ll.y);
}
bool chackpoint(int x,int y)
{
if(a[x][y]==1) return 0;
if(x<1 || x>7 || y<1 || y>7) return 0;
if((x>=3 && x<=5) || (y>=3 && y<=5)) return 1;
return 0;
}
void dfs(int u,int done,int lastpoint,int step)
{
//cout<<step<<endl;
if(step==n-1)
{
printf("%d\n",n-1);
for(int i=1;i<=n-1;i++)
{
printf("%d %d\n",mox[i],moy[i]);
if(st[i]==1) printf("Down\n");
else if(st[i]==2) printf("Up\n");
else if(st[i]==3) printf("Right\n");
else if(st[i]==4) printf("Left\n");
}
exit(0);
}
if(step>n) return;
for(int i=n;i>=1;i--)
{
for(int k=1;k<=4;k++)
{
int px=p[i].x+w[1][k];
int py=p[i].y+w[2][k];
int qx=p[i].x+w[1][k]/2;
int qy=p[i].y+w[2][k]/2;
if(a[p[i].x][p[i].y] && a[qx][qy] && chackpoint(px,py))
{
a[p[i].x][p[i].y]=0;
a[px][py]=1;
a[qx][qy]=0;
mox[++tot]=p[i].x;
moy[tot]=p[i].y;
st[tot]=k;
p[i].x=px;
p[i].y=py;
dfs(u-1,k,i,step+1);
p[i].x=px-w[1][k];
p[i].y=py-w[2][k];
a[p[i].x][p[i].y]=1;
a[px][py]=0;
a[qx][qy]=1;
tot--;
}
}
}
}
int main()
{
freopen("chemistry.in","r",stdin);
freopen("chemistry.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
a[p[i].x][p[i].y]=1;
}
sort(p+1,p+1+n,cmp);
for(int i=1;i<=n;i++)
{
for(int k=1;k<=4;k++)
{
int px=p[i].x+w[1][k];
int py=p[i].y+w[2][k];
int qx=p[i].x+w[1][k]/2;
int qy=p[i].y+w[2][k]/2;
if(a[p[i].x][p[i].y] && a[qx][qy]==1 && chackpoint(px,py))
{
a[p[i].x][p[i].y]=0;
a[px][py]=1;
a[qx][qy]=0;
mox[++tot]=p[i].x;
moy[tot]=p[i].y;
st[tot]=k;
p[i].x=px;
p[i].y=py;
dfs(n-1,k,i,1);
p[i].x=px-w[1][k];
p[i].y=py-w[2][k];
a[p[i].x][p[i].y]=1;
a[px][py]=0;
a[qx][qy]=1;
tot--;
}
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
3.语文
这是一道…逗比题。真是不懂这道题考察的点啊,打一个懒标记并在上传过程中不断得出答案就可以A了这道题,读题加上码码一共耗时5分多钟。可以说数据也是相当的弱鸡了,居然没有出一个极限的长链来卡我….
题意:给你一棵有N个结点的树和每个点的点权值,并让你处理M个操作,操作有两种形式:p i j,既使以i为根的子树中的所有结点(不包括i点)的权值都+j,u i,既查询i点的点权值。
思路:正常建树,每次p操作时,在i点打上懒标记,在每次u操作时向上累加标记,因为i点一定是它每个祖先结点的子树中的点。最后用标记的累加值加上点权值,得出答案。
(这道题的数据有毒,数据与题目藐视完全不符而且逻辑有障碍)
/*
2016.8.5CHN
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
int fa[500005];
int lazy[500005];
int val[500005];
int query(int k)
{
if(k==0) return 0;
return query(fa[k])+lazy[k];
}
int main()
{
freopen("stdkiller.in","r",stdin);
freopen("stdkiller.out","w",stdout);
scanf("%d%d%d",&n,&m,&val[1]);
for(int i=2;i<=n;i++) scanf("%d%d",&val[i],&fa[i]);
for(int k=1;k<=m;k++)
{
char c;
scanf("%c%c",&c,&c);
if(c=='p')
{
int x,y;
scanf("%d%d",&x,&y);
lazy[x]+=y;
}
if(c=='u')
{
int x;
scanf("%d",&x);
/*
printf("%d ",fa[x]);
cout<<query(0)<<" "<<val[x]<<" ";*/
printf("%d\n",query(fa[x])+val[x]);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
今天的题解更新晚了,对不起各位!