NOIP2001提高组

2001提高
A.一元三次方程求解(枚举+二分答案) 水题写挂orz
B.数的划分(dfs/dp)这递推我哪会啊。。。
C.统计单词个数(字符串+暴力+区间dp)这题我哪读得懂啊。。。
D.Car的旅行路线(建图spfa)

A

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define eps 1e-4
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
double a,b,c,d,ans[4];
int num=0;
double cal(double x){return x*x*x*a+x*x*b+x*c+d;}
double calc(int x){
    double l=x,r=x+1;
    while(r-l>=eps){
        double mid=(l+r)/2;
        if(cal(mid)*cal(x)>0) l=mid;else r=mid;
    }return l;
}
int main(){
//  freopen("testdata.in","r",stdin);
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    for(int x=-100;x<=99;++x){
        if(abs(cal(x))<eps){ans[++num]=x;continue;}
        if(abs(cal(x+1))<eps) continue;
        if(cal(x)*cal(x+1)<0) ans[++num]=calc(x);
    }printf("%.2lf %.2lf %.2lf\n",ans[1],ans[2],ans[3]);
    return 0;
}

B

#include<cstdio>
int n,k,sum=0;
void work(int x,int kk,int nn){// x--枚举的数,kk--份数,nn--剩下的数. 
    if(kk==k) sum++;
    else for(int i=x;i<=nn/(k-kk+1);++i) work(i,kk+1,nn-i);
    //i<=nn/(k-kk+1)使答案非降序排列,避免重复
}
int main(){
    scanf("%d%d",&n,&k);
    work(1,1,n);
    printf("%d",sum);
    return 0;
}

或者

根据有没有大小为1的数转移。
dp[n][k]=dp[n-1][k-1]+dp[n-k][k]

C

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 210
#define inf 0x3f3f3f3f
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,kk,m,w[N][N],dp[N][50],len[7];
char s[N],a[7][N];
bool jud(int l,int r){
    for(int i=1;i<=m;++i){
        if(len[i]>r-l+1) continue;
        bool flag=1;
        for(int j=1;j<=len[i];++j)
            if(s[l+j-1]!=a[i][j]){flag=0;break;}
        if(flag) return 1;
    }return 0;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();kk=read();
    for(int i=1;i<=n;++i) scanf("%s",s+1+(i-1)*20);n*=20;
    m=read();for(int i=1;i<=m;++i) scanf("%s",a[i]+1),len[i]=strlen(a[i]+1);
    for(int j=1;j<=n;++j)
        for(int i=j;i>=1;--i)
            w[i][j]=w[i+1][j]+jud(i,j);
    for(int i=1;i<=n;++i) dp[i][1]=w[1][i];
    for(int k=2;k<=kk;++k)
        for(int i=k;i<=n;++i)
            for(int j=k-1;j<i;++j)
                dp[i][k]=max(dp[i][k],dp[j][k-1]+w[j+1][i]);
    printf("%d\n",dp[n][kk]);
    return 0;
}

D

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
#define inf 0x3f3f3f3f
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int tst,n,wa,h[N<<2],num=0;
double dis[N<<2];
bool inq[N<<2];
struct point{
    int x,y;
}a[N][5];
struct edge{
    int to,next;double val;
}data[400000];
inline void add(int x,int y,double val){
    data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
    data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=val;
}
inline int d(point x,point y){return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);}
void spfa(int s){
    queue<int>q;memset(dis,127,sizeof(dis));memset(inq,0,sizeof(inq));
    for(int i=1;i<=4;++i) q.push((s-1<<2)+i),inq[(s-1<<2)+i]=1,dis[(s-1<<2)+i]=0;
    while(!q.empty()){
        int x=q.front();q.pop();inq[x]=0;
        for(int i=h[x];i;i=data[i].next){
            int y=data[i].to;
            if(dis[y]>dis[x]+data[i].val){
                dis[y]=dis[x]+data[i].val;
                if(!inq[y]) q.push(y),inq[y]=1;
            }
        }
    }
}
int main(){
//  freopen("a.in","r",stdin);
    tst=read();
    while(tst--){
        n=read();wa=read();int s=read(),t=read();num=0;
        memset(h,0,sizeof(h));
        for(int i=1;i<=n;++i){
            for(int j=1;j<=3;++j) a[i][j].x=read(),a[i][j].y=read();
            int v=read(),l1=d(a[i][1],a[i][2]);
            int l2=d(a[i][1],a[i][3]),l3=d(a[i][2],a[i][3]);
            if(l1>l2&&l1>l3) a[i][4].x=a[i][1].x+a[i][2].x-a[i][3].x,a[i][4].y=a[i][1].y+a[i][2].y-a[i][3].y;
            else if(l2>l1&&l2>l3) a[i][4].x=a[i][1].x+a[i][3].x-a[i][2].x,a[i][4].y=a[i][1].y+a[i][3].y-a[i][2].y;
            else a[i][4].x=a[i][3].x+a[i][2].x-a[i][1].x,a[i][4].y=a[i][3].y+a[i][2].y-a[i][1].y;
            add((i-1)*4+1,(i-1)*4+2,sqrt(l1)*v);add((i-1)*4+1,(i-1)*4+3,sqrt(l2)*v);
            add((i-1)*4+3,(i-1)*4+2,sqrt(l3)*v);
            for(int j=1;j<=3;++j) add(i*4,(i-1)*4+j,sqrt(d(a[i][4],a[i][j]))*v);
            for(int j=1;j<i;++j)
                for(int ii=1;ii<=4;++ii)
                    for(int jj=1;jj<=4;++jj)
                        add((i-1<<2)+ii,(j-1<<2)+jj,sqrt(d(a[i][ii],a[j][jj]))*wa);
        }double ans=inf;spfa(s);for(int i=1;i<=4;++i) ans=min(ans,dis[(t-1<<2)+i]);
        printf("%.1f",ans);
    }return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值