360笔试(3-18)编程题

1.给一个半径为R的圆,圆心是(0,0),开始位于(R,0),分别求从始点顺时针和逆时针走长度为L的终点坐标

 有可能走多圈,先处理成走一圈的形式,然后判是不是四个断点,如果是则输出

  然后把L处理到第一象限,与x轴形成的夹角是L/R,y点坐标就是R*sin(L/R),那么x=sqrt(R*R-x*x)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const double pi=acos(-1);
const double esp=1e-8;
double L,R,S;

void solve(double &x,double& y,double l){
    double jiao=(l/S)*pi*2;
    y=R*sin(jiao);
    x=sqrt(R*R-y*y);
}

int main(){
    cin>>L>>R;
    S=pi*R*2;
    while(L>=S)L-=S;
    
    
    //先判断四个端点
    if(abs(L)<=esp){
        printf("%.3f %.3f\n",R,0);
        printf("%.3f %.3f\n",R,0);
        return 0;
    }
    else if(abs(L-(S/4))<=esp){
        printf("%.3f %.3f\n",0,R);
        printf("%.3f %.3f\n",0,-R);
        return 0;
    }
    else if(abs(L-(S/4)*2)<=esp){
        printf("%.3f %.3f\n",-R,0);
        printf("%.3f %.3f\n",-R,0);
        return 0;
    }
    else if(abs(L-(S/4)*3)<=esp){
        printf("%.3f %.3f\n",0,-R);
        printf("%.3f %.3f\n",0,R);
        return 0;
    }
    
    // 假设顺时针的话,然后判断在哪个象限
    double x,y;
    
    if(L<(S/4)){
        solve(x,y,L);
    }
    else if(L<(S/2)){
        L=S/2-L;
        solve(x,y,L);
        x*=-1;
    }
    else if(L<(S/4)*3){
        L-=S/2;
        solve(x,y,L);
        x*=-1;y*=-1;
    }
    else{
        L=S-L;
        solve(x,y,L);
        y*=-1;
    }
    
    printf("%.3f %.3f\n",x,-y);
    printf("%.3f %.3f\n",x,y);
    
    
    
    return 0;
}
View Code

2.给一个长度是n的串,串中只有1-9这9个数字,求把这个串拆分若干个字串,每个字串中没有重复的数字,输出有多少种分割方法,答案mod1000000007

做选择做的有点紧张,读错题了,简单dp,dp[i]表示分割前i个的种类,如果从j分割,那么j以及前面的是一个分割方法,(j+1)-i是一个分割,那么dp[i]=sigma(dp[j])j表示从i往回走,能走到的无重复的最远距离

简单题,血亏

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1000000007;
int a[maxn],v[10];
int dp[maxn];

int main(){
    //freopen("in.txt","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",a+i);
    dp[0]=1;
    for(int i=1;i<=n;i++){
        for(int j=i-1;j>=0;j--){
            if(v[a[j+1]])break;
            v[a[j+1]]=1;
            dp[i]=(dp[i]+dp[j])%mod;
        }
        memset(v,0,sizeof(v));
    }
    printf("%d\n",dp[n]);
    return 0;
}
View Code

3.有一个双端队列,两个海盗分金子,每人轮流在取一个金子,可以在左端或者右端每次取一个金子,两人都会做最有选泽,输出先手和后手的得到的最多金子

博弈dp,记忆化搜索就能解,dp[i][j][2],表示i-j之间,第一个人个第二个人能得到的最佳答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=505;
int a[maxn];
int dp[maxn][maxn][2];
typedef pair<int,int> pr;
int t,n;

void dfs(int l,int r,int cnt){
    if(dp[l][r][cnt]!=-1)return ;
    if(l==r){
        dp[l][r][cnt]=a[l];
        dp[l][r][cnt^1]=0;
        return ;
    }
    dfs(l+1,r,cnt^1);
    dfs(l,r-1,cnt^1);
    int L=dp[l+1][r][cnt]+a[l],R=dp[l][r-1][cnt]+a[r];
    //cout<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
    if(L>R){
        dp[l][r][cnt]=L;
        dp[l][r][cnt^1]=dp[l+1][r][cnt^1];
    }
    else{
        dp[l][r][cnt]=R;
        dp[l][r][cnt^1]=dp[l][r-1][cnt^1];
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    int cas=1;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0;i<n;i++)cin>>a[i];
        memset(dp,-1,sizeof(dp));
        dfs(0,n-1,0);
        
        printf("Case #%d: %d %d\n",cas++,dp[0][n-1][0],dp[0][n-1][1]);
    }
    return 0;
}

 

posted @ 2017-03-19 09:15  N维解析几何  阅读(175)  评论(0编辑  收藏  举报