Google APAC Test 2017 Round D

来源:互联网 发布:淘宝上怎么修改会员名 编辑:程序博客网 时间:2024/05/18 18:03

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