Google APAC Test 2017 Round D

Problem A. Vote

扩展卡特兰数。
n个1,m个0,n > m 要保证任意一个位置1的个数都大于0的个数。
保证第一个数为1,后面n - 1个1和m个0符合扩展卡特兰数即可
扩展卡特兰数参考题:HDU 1133
参考题解:例如这里
n - 1个1,m个0构成的卡特兰数的最终解为ans = C(n + m - 1, n - 1) - C(n + m - 1,n)
最终答案为ans * n! * m! / (n + m)!
这里写图片描述
最终结果就可以化简成这样。。。

int main()
{
    freopen("A-large-practice.in","r",stdin);
    freopen("A-large-practice.out","w",stdout);
    int T,N,M;
    cin>>T;
    for(int cas = 1;cas <= T;cas ++)
    {
        cin>>N>>M;
        double ans = (N - M)*1.0 / (N + M);
        cout<<"Case #"<<cas<<": ";
        printf("%.8lf\n",ans);
    }
    return 0;
}

Problem B. Sitting

个人想法:
N行M列,如果N < 2 或 M < 2,最好的排列方式就是:
xxo xxo xxo xxo…
xxo xxo xxo xxo…
这样能达到最大。
当N >= 3 && M >= 3时,则符合条件的排列方法就是
xxo xxo xxo xxo…
xox xox xox xox…
oxx oxx oxx oxx…
xxo xxo xxo xxo…
xox xox xox xox…
或者
xox xox xox xox…
xxo xxo xxo xxo…
oxx oxx oxx oxx…
xox xox xox xox…
xxo xxo xxo xxo…
等等。
以3*3为一个单元。
但是
xxo xxo xxo xxo…
xox xox xox xox…
oxx oxx oxx oxx…
xxo xxo xxo xxo…
xox xox xox xox…
是最好的排列方式。
例如N = 4, M = 8;
xxo xxo xx
xox xox xo
oxx oxx ox
xxo xxo xx
就比
xox xox xo
xxo xxo xx
oxx oxx ox
xox xox xo
要好。
左上角的x越多越好。

int getAns(int N,int M)
{
    int ans;
    if(M == 2 || N == 2)
    {
        if(N > M) swap(N,M);
        if(M % 3 == 1)
            ans = ((M / 3) * 2 + 1) * N;
        else
            ans = ((M + 1) / 3) * 2 * N;
    }
    else
    {
        ans = (N / 3) * 2  * M ;
        if(N % 3 != 0)
            ans += (N % 3) * ((M + 2) / 3) + (N % 3 - 1) * (M/ 3) +   ((M + 1) / 3) ;
    }

    return ans;
}

int main()
{

    freopen("B-large-practice.in","r",stdin);
    freopen("B-large-practice.out","w",stdout);
    int T,N,M;
    cin>>T;
    for(int cas = 1;cas <= T;cas ++)
    {
        cin>>N>>M;
        cout<<"Case #"<<cas<<": "<<getAns(N,M)<<endl;
    }
    return 0;
}

Problem C. Codejamon Cipher

dp
dp[i] 表示到第i位为止可以构成多少种可能性。
dp[i] += dp[i - j] * x (x: num of sorted string from i to j. )

map<string,int> mp;
const int Maxn = 4100;
const int Mod = 1000000007;
int dp[Maxn];
int solved(string s,int maxLen)
{
    int sz = s.length();
    for(int i = 0;i < sz;i ++)
    {
        string tmp = "",str;
        int range = i - maxLen + 1;
        if(range < 0) range = 0;
        dp[i] = 0;
        for(int j = i;j >= range;j --)
        {
            tmp += s[j];
            str = tmp;
            sort(str.begin(),str.end());
            if(mp.find(str) != mp.end())
            {
                dp[i] = (dp[i] + ((j < 1 )?1:dp[j - 1] )* mp[str] % Mod) % Mod;
                if(dp[i] < 0) dp[i] += Mod;
            }
        }
    }
    return dp[sz - 1];
}
int main()
{
    freopen("C-large-practice.in","r",stdin);
    freopen("C-large-practice.out","w",stdout);
    int T,N,M;
    string s;
    cin>>T;
    for(int cas = 1;cas <= T;cas ++)
    {
        cin>>N>>M;
        mp.clear();
        int maxLen = 0;
        for(int i = 0;i < N;i ++)
        {
            cin>>s;
            sort(s.begin(),s.end());
            mp[s]++;
            maxLen = max(maxLen,int(s.length()));
        }
        cout<<"Case #"<<cas<<": ";
        for(int i = 0;i < M;i ++)
        {
            cin>>s;
            if(i != 0) cout<<" ";
            cout<<solved(s,maxLen);
        }
        cout<<endl;


    }
    return 0;
}

Problem D. Stretch Rope

也是一道dp
M虽然会很大,但是L小,所以从L 入手。
dp[i] 表示当构成长度为i时所需要的最小的花费。
dp[i] = min(dp[i],min(dp[i - L],…..,dp[i - R]) L,R表示当前要加入的rubber的区间范围

下面代码大数据跑了几分钟,如果要优化的话就是求区间最小值的一个优化

const int Inf = 0x7fffffff;
const int Maxn = 1100;
struct node
{
    int a,b,p;
};
node nd[Maxn];
int cost[10010];
int main()
{
    freopen("D-large-practice.in","r",stdin);
    freopen("D-large-practice.out","w",stdout);
    int T,N,M,L;
    cin>>T;
    for(int cas = 1;cas <= T;cas ++)
    {
        cin>>N>>M>>L;
        int maxR = 0;
        for(int i = 0;i < N;i ++)
        {
            cin>>nd[i].a>>nd[i].b>>nd[i].p;
            maxR += nd[i].b;
        }
        cout<<"Case #"<<cas<<": ";
        if(maxR < L)
            cout<<"IMPOSSIBLE"<<endl;
        else
        {
            for(int i = 1;i <= L;i ++)
                cost[i] = Inf;
            cost[0] = 0;
            for(int i = 0;i < N;i ++)
            {
                for(int j = L;j >= nd[i].a;j --)
                {
                    int Min = Inf;
                    for(int k = j - nd[i].a;k >= j - nd[i].b && k >=0;k--)
                        Min = min(cost[k],Min);
                    if(Min != Inf)
                        cost[j] = min(cost[j],Min + nd[i].p);

                }
            }
            if(cost[L] > M)
                cout<<"IMPOSSIBLE"<<endl;
            else
                cout<<cost[L]<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值