【建兰普及模拟赛第一场】20181023

T1:真的是简单的模拟,再简单不过了,其实就是求这个里面那个比值最小。
要注意他当前这个店也是要算在比较的范围内的。

#include <bits/stdc++.h>
using namespace std;
const int Inf=1<<30;
inline int read() {
    int w=0,x=0; char ch=0;
    while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return w?-x:x;
}
double Max(double n,double m) {return n>m?n:m;}
double Min(double n,double m) {return n<m?n:m;}
int main() {
    int xncs=read(),ynsc=read(),n=read();
    double ans=(1.0*xncs)/(1.0*ynsc);
    for (int i=1;i<=n;i++) ans=Min(1.0*read()/(1.0*read()),ans);
    printf("%0.2lf\n",ans*1000);
    return 0;
}

T2:真的是简单的模拟,还是非常简单的。我是O(6^3)枚举全部的情况,然后在检查一下是否合法就可以了,要注意字典序要是最小的。

var
    st:array[1..6]of string;
    ans,tmp:string;
    i,j,k:longint;
    
function check(x,y,z:longint):boolean;
var
    map:array[1..3,1..3]of char;
    vis:array[1..6]of boolean;
    s:string;
    fg:boolean;
    i,j,k:longint;
begin
    for i:=1 to 6 do vis[i]:=true; vis[x]:=false; vis[y]:=false; vis[z]:=false;
    for i:=1 to 3 do map[1][i]:=st[x][i];
    for i:=1 to 3 do map[2][i]:=st[y][i];
    for i:=1 to 3 do map[3][i]:=st[z][i];
    for i:=1 to 3 do 
    begin
        s:=map[1][i]+map[2][i]+map[3][i];
        fg:=false;
        for j:=1 to 6 do 
            if (j<>x)and(j<>y)and(j<>z) then 
                if (vis[j])and(s=st[j]) then 
                begin
                    fg:=true;
                    vis[j]:=false;
                    break;
                end;
        if (fg=false) then  exit(false);
    end;
    exit(true);
end;

begin
    assign(input,'match.in'); reset(input);
    assign(output,'match.out'); rewrite(output);
    for i:=1 to 6 do readln(st[i]);
    ans:='ZZZZZZZZZ';
    for i:=1 to 6 do 
        for j:=1 to 6 do 
        begin
            if (i=j) then continue;
            for k:=1 to 6 do 
            begin
                if (i=k)or(j=k) then continue;
                tmp:=st[i]+st[j]+st[k];
                if (check(i,j,k))and(ans>tmp) then ans:=tmp;
            end;
        end;
    if (ans='ZZZZZZZZZ') then writeln(0)
    else 
    begin
        for i:=1 to 3 do 
        begin
            for j:=1 to 3 do write(ans[(i-1)*3+j]);
            writeln;
        end;
    end;
end.

T3:真的是卡特兰数,我们一般知道的推导公式是

o_%E5%9B%BE%E7%89%871.png

但是,卡特兰数是非常大的,这里是要%%%的,所以这个公式我们就用不了了。
所以我们要换一个公式:
f(n)=f(0)(n-1)+f(1)f(n-1)+...+f(n-1)*f(0)
这个公式因为是只是涉及到加法的公式,所以我们随便%%%。
那么就好了。(这道题做不出来,那么就是初赛没有好好复习)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL Mod=100000007;
inline int read() {
    int w=0,x=0; char ch=0;
    while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return w?-x:x;
}
LL f[3005];
int main() {
    freopen("cirs.in","r",stdin);
    freopen("cirs.out","w",stdout);
    int n=read();
    f[1]=f[0]=1; 
    for (int i=2;i<=n;i++) {
        for (int j=0;j<i;j++) {
            f[i]=(f[i]+f[j]*f[i-j-1])%Mod;
        }
    }
    printf("%lld\n",f[n]);
    return 0;
}

T4:真的是动态规划,不知道有没有看出来是背包,算了不管了。
我们需要知道两大核心,两大思路。
核心1:状态:F[i][j]表示第i辆车,人数为j的最少钱
核心2:状态转移方程:
我们参照一下背包:f[i][j]=max(f[i][j],f[i-1][j-w[i]]+v[i]);
滚动♂优化:f[j]=max(f[j],f[j-w[i]]+v[i]);
我们就可以参照一下这个思路,我们就考虑选和不选的情况
不选就是f[i-1][j],也就是这个车子是空的?Why?因为f[i][j]表示这个车i个人,j个人。但是f[i-1][j]有表示i-1辆车中有j个人,那么就是不是就是这个第i辆车是不是就是没有人了。
那么选的情况就是f[i-1][j-s]+d+sv
是不是这个意思,我们枚举一个s就可以了,表示的就是当前这个第i辆车的人数。
我们要求最小值,那么就去一个min可以了。
那么我们就滚动优化一下:f[j]=min(f[j],f[j-t]+d+t
a)
好像是不是更优了一点QAQ!

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <algorithm>
using namespace std;
const int Inf=0x3f3f3f3f;
int n,k,d,s,a,b;
int f[105][105];
inline int read() {
    int w=0,x=0;char ch=0;
    while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 
    return w?-x:x;
}
int main() {
    n=read(),k=read(),d=read(),s=read(); 
    memset(f,Inf,sizeof(f));
    f[0][0]=0;
    for (int i=1;i<=k;i++) {    
        a=read(),b=read();
        for (int j=0;j<=n;j++) {
            f[i][j]=f[i-1][j];
            for (int t=0;t<=b;t++) {
                if (j>=t) f[i][j]=min(f[i][j],f[i-1][j-t]+d+t*a);
            }
        }
    }
    if (f[k][n]!=Inf) printf("%d\n",f[k][n]);
    else printf("impossible\n");
    return 0;
}

(滚动优化,还未测试)

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <algorithm>
using namespace std;
const int Inf=0x3f3f3f3f;
int n,k,d,s,a,b;
int f[105];
inline int read() {
    int w=0,x=0;char ch=0;
    while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 
    return w?-x:x;
}
int main() {
    n=read(),k=read(),d=read(),s=read(); 
    memset(f,Inf,sizeof(f));
    f[0]=0;
    for (int i=1;i<=k;i++) {    
        a=read(),b=read();
        for (int j=0;j<=n;j++) {
            for (int t=b;t>=0;t--) {
                if (j>=t) f[j]=min(f[j],f[j-t]+d+t*a);
            }
        }
    }
    if (f[k]!=Inf) printf("%d\n",f[k]);
    else printf("impossible\n");
    return 0;
}

转载于:https://www.cnblogs.com/Dawn-Star/p/9839351.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值