T1.淘汰赛制

    比赛时的淘汰赛制,给出每两个球队比赛的胜率,求出最终胜率最高的队伍。

       这题的概率真的很难算啊感觉。。。一开始打的代码打下来就是用f[i][j]表示i场比赛后第j人还在场的概率。不难看出这是一棵树形的状态树

那么可以看出,每次比较的区间长度是2n,那么可以通过枚举左端点来确定区间。确定区间后,f[i][j]=f[i-1][j]*sum(f[i-1][k]*a[j][k])

T2.种树(trees)

    有长度为n的区间,有h个要求,每个要求为[b,e]内至少标记t个数,求最少标记数。

       贪心吧。。。

一种做法是先把区间按e,b排序,然后先满足e小的需求,尽量往e靠,每次先计算此区间内已被标记的,然后标记未被标记的直到满足条件,最后扫一遍计算被标记的数;

另一种做法是类似的,每次标记后,搜索后面的区间,如果当前标记点在那个区间内,则减少那个区间的要求量,重复动作直到当前区间需求减少为0。每次检查新区间的时候就把要求量加入ans,最后输出ans即可。

由于第一个做法较简单,第二个较难描述,所以放一下第二种做法的代码。

#include <iostream>

#include <cstdio>

#include <algorithm>

using namespace std;

 

struct request

{

         int b,e,t;

         bool operator < (const request &xx) const

         {

                   return e==xx.e?b<xx.b:e<xx.e;

         }

}q[5011];

int n,h;

int v[30011];

 

int main()

{

         freopen("trees.in","r",stdin);

         freopen("trees.out","w",stdout);

         cin >> n;

         cin >> h;

         for (int i=1;i<=h;i++)

         {

                   cin >> q[i].b >> q[i].e >> q[i].t;

         }

         sort(q+1,q+h+1);

         int cnt=0;

         for (int i=1;i<=h;i++)

         {

                   if (q[i].t>0)

                   {

                            int pos=q[i].e;

                            cnt+=q[i].t;

                            for (int j=1;j<=q[i].t;j++)

                            {

                                     while (v[pos])

                                               pos--;

                                     v[pos]=1;

                                     for (int k=i+1;k<=h;k++)

                                               if (q[k].b<=pos&&pos<=q[k].e)

                                                        q[k].t--;

                            }

                   }       

         }

         cout << cnt << "\n";

}

T3.软件开发(software)

    有两个项目各有m个步骤,由n个人来完成,每个人完成同一任务的一个步骤时间不变,求出完成的最少时间。(题目给出了每个人完成这两个任务的时间)

       一看感觉题目有点熟悉,然后就开始dp。一开始的状态是f[i][j][k],表示前i个人完成第一个任务的j个步骤,第二个任务的k个步骤所需的最短时间。打了五重循环然后发现是错的,因为每个人的效率是不同的。所以没有交,换了一种打法。

       先二分时间,然后就是判断这个时间下是否可行了。判断也是一个dp的过程,f[i][j]表示前i个人做了第一个任务的j个步骤时,还能做第二个任务的步骤数。f[i][j]=max(f[i][j],f[i-1][k]+(t-(j-k)*d1[i])/d2[i])

(d1[i],d2[i]分别表示第i个人做两个任务的一个步骤的时间)。如果最后f[n][m]>=m就表示可行。

       如此就能AC了。

(但是第一遍为什么只有40分呢?这就和我当时处理f[1][j]的时候不谨慎有很大关系了,还有一处错就是我把j*d1[i]>t的情况全部舍去了,就把一些情况漏掉了。。。)

posted on 2016-10-05 13:02  啊?  阅读(119)  评论(0编辑  收藏  举报