A.Grandpa's Walk
简单的搜索题,此题的题意是将nXm的图中所有能降序走通的道路求出来。就是一个dfs深搜,没有难度。
写得很简单,没有考虑太多。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int n,m,sum,c[51][51];
void dfs(int x,int y)
{
int i,j,k,g=0;
For(0,4,k)
{
i=x+dx[k];
j=y+dy[k];
if(c[i][j]<c[x][y]&&(i>=0&&j>=0&&i<n&&j<m))//深搜
{
dfs(i,j);
g=1;
}
}
if(g==0)
{
sum++;
}
}
int main()
{
int i,j,k,t,cas=0,a,b,f;
RD(t);
while(t--)
{
cas++;
RD(n);
RD(m);
For(0,n,i)
{
For(0,m,j)
{
RD(c[i][j]);
}
}
sum=0;
For(0,n,i)
{
For(0,m,j)
{
f=0;
For(0,4,k)
{
a=i+dx[k];
b=j+dy[k];
if(c[a][b]>c[i][j]&&(a>=0&&b>=0&&a<n&&b<m))//判断此点能否作为起点
{
f=1;
}
}
if(f==0)
{
dfs(i,j);
}
}
}
printf("Case #%d: %d\n",cas,sum);
}
return 0;
}
B.Let's Go Green
咋一眼看上去像是一道图论题,但我图论很水,就再想了一下,发现这是一个比较巧妙的想法题。我们可以将这个图看成一条主干路,边上有一些小的岔路分支,我们首先将所有点周围的连接路径上的BY都加上,并记录它周围BY最多的一条路径。接下去就是计算了,我们首先把所有的分支和端点上路径的BY数都加上,我们可以这样想:所有的支路的BY最后都是要加到主干路上的,有一个分叉就得加上该条的BY数。接下去再分析结点,对于一个BY最多一条路径比剩余BY数还多的结点,我们需要加上最多BY比剩余部分多的内部分,然后再分析一个BY最多一条路径比剩余BY数还少的结点,只要判断是奇数就加上1,不是就不加。可以这样理解(偶数的此种结点其周围BY会自动形成两边相等的情形,所以不需要加,而奇数的该结点两端无法平衡,必然相差1,所以需要加1),最后得到答案后需要除以2,因为这是一个两端相等的和。
说得不太清楚,表达能力有限请原谅~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
struct xl
{
int x[100001],y[100001];
}p;
int main()
{
int t,n,a,b,c,i,z,s,cas=0;
RD(t);
while(t--)
{
cas++;
RD(n);
mem(p.x,0);
mem(p.y,0);
z=0;
for(i=0;i<n-1;++i)
{
RD(a);
RD(b);
RD(c);
p.x[a]+=c;
p.x[b]+=c;
p.y[a]=max(p.y[a],c);
p.y[b]=max(p.y[b],c);
}
s=0;
for(i=1;i<=n;++i)
{
if(2*p.y[i]>p.x[i])
{
s+=(2*p.y[i]-p.x[i]);
}
else if(p.x[i]%2==1)
{
s+=1;
}
}
printf("Case #%d: %d\n",cas,s/2);
}
return 0;
}
C.Stop Growing!
水题不多说,自己看。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int main()
{
int t,a,b,c,d,e,sum,ans,m,j,cas=0;
RD(t);
while(t--)
{
cas++;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&m);
sum=a+b+c+d+e;
if(sum<=0&&sum<m)
{
printf("Case #%d: -1\n",cas);
}
else
{
j=0;
while(sum<m)
{
sum*=2;
j++;
}
printf("Case #%d: %d\n",cas,j);
}
}
return 0;
}
G题是个双连通分量,图论渣不会。。。就不写了
I.Tiling
题意,给你六个系数,让你分别求出xi,yi,求这些点中能覆盖的最小面积模块
图给你示意图太误导人了,我们可以直接考虑同一行的x之间的距离就行了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include <queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
return gcd(b,a%b);
}
int det(int a,int b,int x,int y)
{
return abs(a*y-b*x);
}
int main()
{
int t,cas=0,i,x1,x2,x3,y1,y2,y3,a,b,c;
RD(t);
while(t--)
{
cas++;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3);
a=det(x1,y1,x2,y2);
b=det(x1,y1,x3,y3);
c=det(x2,y2,x3,y3);
printf("Case #%d: %d\n",cas,gcd(a,gcd(b,c)));
}
return 0;
}
J.Perfect Matching
简单题,但是容易卡时间,题意就是给你n个字符串,让你两两搭配,看是否为回文字符串。思路一样,有些能AC,有些TLE,这就要看你写得优不优美了~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
char a[1001][501];
string str;
int main()
{
int t,n,i,j,cas=0,l,f,sum,k;
RD(t);
while(t--)
{
cas++;
RD(n);
sum=0;
for(i=0; i<n; ++i)
{
scanf("%s",a[i]);
}
for(i=0; i<n; ++i)
{
for(j=0; j<n; ++j)
{
if(i!=j)
{
str=a[i];
str+=a[j];
l=str.length();
f=0;
for(k=0; k+k<l; ++k)
{
if(str[k]!=str[l-k-1])
{
f=1;
break;
}
}
if(f==0)
{
sum++;
}
}
}
}
printf("Case #%d: %d\n",cas,sum);
}
return 0;
}