考察知识:二分,枚举
算法难度:XX 代码实现难度:XX
Tips:'X'越多表示越难
分析:这道题给定的一元三次方程限制比较多,减少了难度,我们可以考虑枚举区间长为1的区间(-100~100),二分答案,题目提示所得比较清晰,说明开区间 (l,r) 之间有根,我们采用二分法即可
代码实现:
#include
#include
using namespace std;
const double eps=10e-5;
double A,B,C,D;
double f(double x){
return A*x*x*x+B*x*x+C*x+D;
}
#define ABS(x) ((x)>0?(x):-(x))
int main(){
int root=0;
cin>>A>>B>>C>>D;
for(double k=-100;k<=100;k+=1){
if(root==3) break;
if(ABS(f(k)==0)) printf("%.2f ",k),root++;
double l=k,r=k+1;
if(f(l)*f(r)>=0) continue;//在区间(l,r)没有根
while(r-l>=eps){
double mid=(l+r)/2;
if(f(mid)*f(l)<=0) r=mid;
else l=mid;
}
printf("%.2f ",l),root++;
}
return 0;
}
考察知识:动态规划,搜索+剪枝
算法难度:XX 代码实现难度:XX
分析:这道题数据范围不大,可以考虑搜索,下面仅介绍搜索算法:
因为划分的数不考虑顺序,我们可以按照升序从1到k枚举每一个数可能的取值
剪枝:如果后面的数全部与当前数相同还大于n,则剪枝
#include
using namespace std;
int n,k,ans;
void dfs(int cur,int pre,int left){
if(cur==1) {ans++;return;}
for(int i=pre;i<=left/cur;i++)
dfs(cur-1,i,left-i);//剪枝条件包含在对i的限制中
}
int main(){
cin>>n>>k;
dfs(k,1,n);
cout<
考察知识:动态规划,字符串
算法难度:XXX 实现难度:XXX
分析:按动态规划一贯套路来分析
定义状态方程:f(i,k)表示字符串str[0]..str[i]分成k组包含最多单词数
状态转移方程:f(i,k)=max:f(x-1,k-1)+g[x][i] || k<=x<=i
其中的g[x][y]表示子串str[x]..str[y]包含单词数量
边界:f(i,1)=g[0][i]
答案:f(len-1,k)
这道题难度主要在g[i][j]的计算上,考察字符串操作,具体方法见代码calc()函数
对于状态转移方程,我们考虑用记忆化搜索,比较容易实现
注意:我的代码里用了很多容易混淆的变量名,最开始我都把k_写成了k
#include
#include
#include
#include
#include
using namespace std;
int p,k,s,len,g[205][205],f[205][205];
char str[205],tmp[205],wd[10][205];
bool vis[205][205];
int calc(int x,int y){
char t[205];
strcpy(tmp,str+x);
tmp[y-x+1]='\0';
int cnt=0;
for(int i=0;i
考察知识:图的最短路,计算几何
算法难度:XXX 实现难度:XXXX
分析:这道题并不是非常难,只是稍微有点繁琐,其中根据矩形三点求另一点稍微有点麻烦
把图建好后直接用dijkstra或spfa就解决了,考虑到当时不能用STL,可以使用spfa+手工队列
代码:(dijkstra和spfa都有,所以代码显得有点长)
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x7fffffff;
#define FD(p1,p2) ((x[p1]-x[p2])*(x[p1]-x[p2])+(y[p1]-y[p2])*(y[p1]-y[p2]))
double Dist(double x_1,double y_1,double x_2,double y_2){
return sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2));
}
struct City{
double x[4],y[4],T;
void in(){
for(int i=1;i<4;i++) scanf("%lf%lf",x+i,y+i);
scanf("%lf",&T);
if(FD(1,2)+FD(2,3)==FD(1,3))//枚举构成直角三角形的直角所在点
x[0]=x[1]+x[3]-x[2],y[0]=y[1]+y[3]-y[2];
else if(FD(1,3)+FD(2,3)==FD(1,2))
x[0]=x[1]+x[2]-x[3],y[0]=y[1]+y[2]-y[3];
else if(FD(1,2)+FD(1,3)==FD(2,3))
x[0]=x[2]+x[3]-y[1],y[0]=y[2]+y[3]-y[1];
// printf("%lf %lf %lf\n",x[0],y[0],T);
}
}ct[105];
struct data{
double dist;
int city,id;
friend bool operator < (data A,data B){
return A.dist>B.dist;
}
};
int n,s,a,b;
double dis[105][4],p;
bool vis[105][4];
void spfa(){
queueq;
memset(vis,0,sizeof(vis));
for(int i=1;i<=s;i++)
for(int j=0;j<4;j++)
dis[i][j]=inf;
for(int i=0;i<4;i++)
dis[a][i]=0,q.push((data){0,a,i});
int i,id_i;
double d;
data T;
while(!q.empty()){
T=q.front();q.pop();
i=T.city,id_i=T.id,d=T.dist;
vis[i][id_i]=false;
for(int j=1;j<=s;j++) if(i!=j)
for(int id_j=0;id_j<4;id_j++){
double d2=Dist(ct[i].x[id_i],ct[i].y[id_i],ct[j].x[id_j],ct[j].y[id_j])*p;
if(d+d2pq;
memset(vis,0,sizeof(vis));
for(int i=1;i<=s;i++)
for(int j=0;j<4;j++)
dis[i][j]=inf;
for(int i=0;i<4;i++)
dis[a][i]=0,pq.push((data){0,a,i});
data T;
int i,id_i;
double d;
while(!pq.empty()){
T=pq.top();pq.pop();
d=T.dist,i=T.city,id_i=T.id;
if(vis[i][id_i]) continue;
vis[i][id_i]=true;
for(int j=1;j<=s;j++) if(i!=j)
for(int id_j=0;id_j<4;id_j++){
double d2=Dist(ct[i].x[id_i],ct[i].y[id_i],ct[j].x[id_j],ct[j].y[id_j])*p;
if(d+d2
个人总结(反思):(可以忽略)
没有严格按考试来做,也就是没有限定时间,没有检查,做完直接提交
100+100+60+60=320
T3:把k_写成了k,丢了40分
T4:居然把坐标公式写错了,居然还得了60分,居然之后还查错还查了大半天?!
320(400)换算为480(600)
哎,总是会出现难以检查的错误,如果只有一次提交机会,静态查错必须得有