NOIP2001提高组题解

T1:一元三次方程求解

考察知识:二分枚举

算法难度:XX 代码实现难度:XX

Tips:'X'越多表示越难

分析:这道题给定的一元三次方程限制比较多,减少了难度,我们可以考虑枚举区间长为1的区间(-100~100),二分答案,题目提示所得比较清晰,f(l)*f(r)< 0说明开区间 (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;
}

T2:数的划分

考察知识:动态规划搜索+剪枝

算法难度: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<

T3: 统计单词个数

考察知识:动态规划字符串

算法难度: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

T4:Car的旅行路线

考察知识:图的最短路计算几何

算法难度: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)

哎,总是会出现难以检查的错误,如果只有一次提交机会,静态查错必须得有

你可能感兴趣的:(竞赛考试,NOIP提高组历年考试)