Codeforces Round #436 (Div. 2)

http://codeforces.com/contest/864

第一次打cf的月赛……

A

题意:给你一个数列,问你能不能保证里面只有两种数且个数相等。2<=n<=100,1<=ai<=100。

水……没看完题就交了结果YES的时候还要输出这两种数是什么,然后就+1了……

#include <iostream>
#define maxn 105
using namespace std;
int n,a,t[maxn],c[maxn],d[maxn];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        t[a]++;
    }
    int cnt=0;
    for(int i=1;i<=100;i++)
    {
        if(t[i])
        {
            c[++cnt]=t[i];
            d[cnt]=i;
        }
    }
    if(cnt!=2)
        cout<<"NO";
    else if(c[1]!=c[2])
        cout<<"NO";
    else
        cout<<"YES"<<endl<<d[1]<<' '<<d[2];
    return 0;
 } 

 

B

题意:给你一个只含字母的字符串,求仅由小写字母构成的最长子串。

从左到右扫一遍同时记录长度len,遇到大写字母就更新答案并把len归零就好了。一遍过。

#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
using namespace std;
int n;
string s;
bool used[300];
int main()
{
    cin>>n>>s;
    int len=0,cnt=0,ans=0;
    for(int i=0;i<n;i++)
    {
        if(isupper(s[i]))
        {
            memset(used,false,300);
            len=0;
            cnt=0;
        }
        else
        {
            len++;
            if(!used[s[i]])
            {
                used[s[i]]=true;
                cnt++;
                ans=max(ans,cnt);
            }
        }
    }
    cout<<ans;
    return 0;
}

 

C

题意:一条直线道路,起点为0,终点为a,有一辆车在起点和终点来回开k次(来算一次,回算一次)。车的油箱有b汽油,每走1路程就耗1汽油。在路上f的位置有一个加油站,可以帮你把油箱加满。问要完成这k次来回最少需要加多少次油。

如果车现在停在加油站,并且油还够开到终点(或者起点)再回头开到加油站,那么显然不用加油。

干脆把加油站当作检查点,每次检查下还剩多少油,判断需不需要加油。k次以后输出结果。如果加了油也回不来加油站,那么输出-1。要注意特判第一回还有最后一回。

四遍才过……

#include <iostream>
using namespace std;
int a,b,f,k;
int main()
{
    cin>>a>>b>>f>>k;
    int ans=0,pet=b-f;
    if(pet<0)
    {
        cout<<-1;
        return 0;
    }
    bool ahead=true;
    for(int i=1;i<k;i++)
    {
        if(ahead)
        {
            if(pet-2*(a-f)>=0)
                pet-=2*(a-f);
            else
                pet=b-2*(a-f),ans++;
        }
        else
        {
            if(pet-2*f>=0)
                pet-=2*f;
            else
                pet=b-2*f,ans++;
        }
        ahead^=1;
        if(pet<0)
        {
            cout<<-1;
            return 0;
        }
    }
    if(ahead)
    {
        if(pet-(a-f)<0)
        {
            if(b-(a-f)>=0)
                ans++;
            else
            {
                cout<<-1;
                return 0;
            }
        }
    }
    else
    {
        if(pet-f<0)
        {
            if(b-f>=0)
                ans++;
            else
            {
                cout<<-1;
                return 0;
            }
        }
    }
    cout<<ans;
    return 0;
}

 

D

题意:给你一个n项数列,里面的数字均在1~n范围内,问最少替换多少个数字才能变成一个1~n的排序,输出字典序最小的方案。

细节貌似有点多,还没做出来……

 

E

题意:有n个物品,每个物品价值为pi,拿起来要ti的时间,但是这个物品在时间大于等于di时就不能拿了。问怎样使拿到的物品价值之和最大。

容易看出这是道傻逼背包题,得f(i,j)=max{f(i-1,j), f(i-1,j-t[i])+p[i]} (j<d[i]且j>=t[i]),答案就是max{f(n,x) | 0<=x<=2000}。

当时还不懂怎么输出方案,比赛完了才想到每次转移记录一下,然后从答案开始逆过来找哪个物品被拿了。

然后交了上去,WA了。跑去看下别人的AC代码,发现别人都对物品按照di升序排序再选了。我也试了一发,交上去马上就A了。

之后才想明白,f(i,j)是按照1,2,...,i的顺序选择物品得到的价值最大值,如果不排序就会导致有些在后面但是d很小的物品选不到。

#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
int n;
struct item { int t, d, p, id; } a[105];
bool cmp(const item& x, const item& y) { return x.d < y.d; }
int dp[105][2005];
bool took[105][2005];
int main()
{
    ios::sync_with_stdio(false);
    int ans = 0;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        a[i].id = i;
        cin >> a[i].t >> a[i].d >> a[i].p;
    }
    sort(a + 1, a + 1 + n, cmp);
    for (int i = 1; i <= n; i++)
    {
        ans = 0;
        for (int j = 1; j <= 2005; j++)
        {
            if (j < a[i].d && j >= a[i].t && dp[i - 1][j - a[i].t] + a[i].p >= dp[i - 1][j])
            {
                dp[i][j] = dp[i - 1][j - a[i].t] + a[i].p;
                took[i][j] = true;
            }
            else
                dp[i][j] = dp[i - 1][j];

            if (dp[i][j] >= dp[i][ans])
                ans = j;
        }
    }
    cout << dp[n][ans] << endl;
    stack<item> s;
    int j = ans;
    for (int i = n; i >= 1; i--)
    {
        if (took[i][j])
        {
            s.push(a[i]);
            j -= a[i].t;
        }
    }
    cout << s.size() << endl;
    while (!s.empty())
    {
        cout << s.top().id << ' ';
        s.pop();
    }
    return 0;
}

 

未完待+1s(可能)

posted @ 2017-09-27 20:01  ssttkkl  阅读(121)  评论(0编辑  收藏  举报