解题思路:
这个题目整体上还是比较简单的,但是注意点相对来讲也是比较多,自己写的时候时间超时了,自己运用了STL中的map,相对数组来讲,map的维护还是比较耗时的。通过这个题目,感觉自己感触最深的一点便是写代码要有一点的洁癖,追求最优最简,以防不经意间的时间超时或是空间超时。比如对于本题目而言,对于字符串的处理既可以进行全部存储,也可以便输入便计算,而通过实际验证,进行二维字符串的存储会时间超时,在数据量极大的情况下,一些操作细节也会决定程序的正确与否。另外,试了一下如果是关同步情况下,耗时更小一些,对于这些,我们要有一定的意识。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,k;
char s[18];
bool label[10]={0};
int cc;
int ans=0;
int main()
{
scanf("%d%d",&n,&k);
if(k>10)
{
cout<<n<<endl;
return 0;
}
for(int i=0;i<n;i++)
{
scanf("%s",s);
int sz=strlen(s);
memset(label,0,sizeof(label));
cc=0;
for(int j=0;j<sz;j++)
{
if(label[s[j]-'0']==0)
{
label[s[j]-'0']=1;
cc++;
if(cc>=10)
break;
}
}
if(cc<k)
ans++;
}
printf("%d\n",ans);
}在这里插入代码片
解题思路:
对于这道题,自己完全错掉了,这个确实是不应该的,不过也好,学到了一些东西。对于做题尤其是在读题环节千万不能够想当然,题目读不准,便不能写程序。对题意的检查远远强于对程序的检查。反映到这道题目上,便是对于半径的平方的说明,这是题目中明确说明的,也不知道怎么就稀里糊涂的略过去了。另外我们要对double进行重认识,该类型的精确位数是有限的,在整数方面较于long long优先级我们需要选择后者。关于这个题目,思路方面比较简单,详细看代码。
代码:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
long long n;
long long locx[1005];
long long locy[1005];
long long ter=0;
long long r=100000000000000;
long long x,y;
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&locx[i],&locy[i]);
}
x=locx[1],y=locy[1];
for(int i=1;i<=n;i++)
{
ter=0;
for(int j=1;j<=n;j++)
{
ter=max(ter,((locx[j]-locx[i])*(locx[j]-locx[i])+(locy[j]-locy[i])*(locy[j]-locy[i])));
}
if(r==ter&&((locx[i]==x&&locy[i]<y)||(locx[i]<x)))
{
x=locx[i],y=locy[i];
}
else if(ter<r)
{
r=ter;
x=locx[i],y=locy[i];
}
}
printf("%lld.00 %lld.00\n",x,y);
printf("%lld.00\n",r);
}在这里插入代码片
解题思路:
对于这道题目,感觉难度比较大,自己在模拟期间思考了一个小时左右,但是没出一点思路。挫败感足足的。完成这道题目,大约需要分四步.1,确定动态规划的方向去解题。2.定出状态,3.状态转移.4.程序优化。回顾了一下自己做题时的过程,准确地讲自己在第一步确定动态规划的方向时尚且有点犹豫,第二步便直接垮掉了。所以讲还是学到了新东西的,不过,自己水平确实有些浅。
仔细想了一下,感觉问题还是出在自己对于二叉搜索树的理解不够深,本质性的东西不敏感。另一方面,应该还是做题量比较少,所以那种灵活的反射性思维不足。对于二叉搜索树,其本质在于递归分二叉,特点在于根节点大于左子树,小于右子树。而本质与特点正说明了定状态,状态转移两部分如何构造。感觉在dp问题面前,一些没有逻辑的思考往往时混乱的,而这种思考要求确实比较高。对树结构而言,我们惯性的思维喜欢从上往下进行思考,而对于本道题,我们是要还原树,所以一种从上往下的思考是不可行的(或是不易行的),我们采取逐渐累积,逐渐构造的形式对整棵树进行还原,这样在dp的解法中才有踪迹可寻。所以状态的定取目的在于合叉,合叉的原则与形式为二叉搜索树的特性。在这里,我们比较清楚的感受到确定“根节点”的意识在树结构的dp中的重要性,这是寻找子问题的关键因素。另一方面,题目中直接给出了有序的数组,这一点有些暗示作用,起码有序数组的子结构很明显是有序的。整体来讲,这道题目利用的时区间dp进行求解,区间dp通常是三重循环,这道题目也一样,第三重循环需要进行枚举。另外一个注意点,在状态更新时,有时解法是利用上一区间更新当前区间状态,有时是利用当前区间更新下一区间的状态,这跟具体思路有关。另外便是复杂度方面,对于两个点公约数是否大于一,在程序中或许需要多次使用,所以我们一次性将其算出并存储下来,否则会超时。
最后,题目给出的gcd算法很优秀,非常简洁,建议背记下来。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
int t,n;
long long func[705];
bool le[705][705];
bool rig[705][705];
bool fun[705][705];
bool label;
int main() {
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
label=0;
memset(func,0,sizeof(func));
memset(le,0,sizeof(le));
memset(rig,0,sizeof(rig));
memset(fun,0,sizeof(fun));
for(int i=1; i<=n; i++) {
scanf("%lld",&func[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(gcd(func[i],func[j])>1)
{
fun[j][i]=1;
fun[i][j]=1;
}
}
}
if(func[1]<=0) {
printf("No\n");
} else {
for(int i=1; i<=n; i++)
le[i][i]=1,rig[i][i]=1;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n-i+1; j++) {
for(int k=j; k<=j+i-1; k++) {
if(le[j][k]&&rig[k][j+i-1]&&j-1>=1&&fun[k][j-1])
rig[j-1][j+i-1]=1;
if(le[j][k]&&rig[k][j+i-1]&&j+i<=n&&fun[k][j+i])
le[j][j+i]=1;
}
}
}
for(int i=1; i<=n; i++) {
if(le[1][i]&&rig[i][n]) {
label=1;
break;
}
}
if(label==1)
printf("Yes\n");
else
printf("No\n");
}
}
}在这里插入代码片