17级2019春季个人训练赛-6

比赛地址 http://acm.sdibt.edu.cn/vjudge/contest/view.action?cid=2193#overview

A - Bit String Reordering

Sample Input
6 3
1 0 0 1 0 1
1 3 2
7 2
1 1 1 0 0 0 0
4 3
15 14
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 2
1 1
0
1
Sample Output
1
12
7
0

题意:输入n,m,然后输入n个数,要求将这六个数分成m个部分。这m个部分里面都相等,边界与周围不同。相邻位置可以交换,问最少的交换次数。

思路:有两种情况,假设给的m个数是1 3 2,要么最后变成011100,要么变成100011,可以计算两个结果中0和1的个数。会有三种情况(两个结果都符合,各符合一个)。当两个结果都符合时,取最小值。根据结果来交换就比较简单了,设结果数组为c,原数组为a,我们比较对应位置的数是不是相等,相等继续,不相等交换该位置的a[i]和a[i+1](前提是a[i+1]与c[i]相等,如果不相等i++),直到结束为止。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=1E9+7;;
const int MM=192600817;
deque <char> q;
string s;
int main()
{
    ll a[20],b[20],c[20],d[20],aa[20],n,m,i,j,ans;
    while(cin>>n>>m)
    {
        memset(a,0,sizeof(a));
        memset(aa,0,sizeof(aa));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        memset(d,0,sizeof(d));
        ll x=0,y=0;
        ans=0;
        for(i=0; i<n; i++)
        {
            cin>>a[i];
            aa[i]=a[i];
            if(a[i]==0)
                x++;
            else
                y++;
        }
        ll e=0,flag=0,cx=0,cy=0,dx=0,dy=0;
        for(i=0; i<m; i++)
        {
            cin>>b[i];
            if(flag==0)
            {
                for(j=0; j<b[i]; j++)
                {
                    c[e]=0;
                    d[e]=1;
                    flag=1;
                    cx++;
                    dy++;
                    e++;
                }
            }
            else
            {
                for(j=0; j<b[i]; j++)
                {
                    c[e]=1;
                    d[e]=0;
                    flag=0;
                    cy++;
                    dx++;
                    e++;
                }
            }
        }
        if(cx==x&&cy==y&&dx==x&&dy==y)//两个结果都满足,取最小值
        {
            ll ans1=0,ans2=0;
            ans1=0;
            for(i=0;i<n;i++)
            {
                if(a[i]==c[i])
                    continue;
                else
                {
                    for(j=i+1;j<n;j++)
                    {
                        if(a[j]==c[i])
                        {
                            swap(a[i],a[j]);
                            ans1++;
                            break;
                        }
                        else
                        {
                            swap(a[i],a[j]);
                            ans1++;
                        }
                    }
                }
            }
            ans2=0;
            for(i=0;i<n;i++)
            {
                if(aa[i]==d[i])
                    continue;
                else
                {
                    for(j=i+1;j<n;j++)
                    {
                        if(aa[j]==d[i])
                        {
                            swap(aa[i],aa[j]);
                            ans2++;
                            break;
                        }
                        else
                        {
                            swap(aa[i],aa[j]);
                            ans2++;
                        }
                    }
                }
            }
            ans=min(ans1,ans2);
        }
        else
        if(dx==x&&dy==y)//只满足第二个结果
        {
            ans=0;
            for(i=0;i<n;i++)
            {
                if(aa[i]==d[i])
                    continue;
                else
                {
                    for(j=i+1;j<n;j++)
                    {
                        if(aa[j]==d[i])
                        {
                            swap(aa[i],aa[j]);
                            ans++;
                            break;
                        }
                        else
                        {
                            swap(aa[i],aa[j]);
                            ans++;
                        }
                    }
                }
            }
        }
        else
        if(cx==x&&cy==y)//只满足第一个结果
        {
            ans=0;
            for(i=0;i<n;i++)
            {
                if(aa[i]==c[i])
                    continue;
                else
                {
                    for(j=i+1;j<n;j++)
                    {
                        if(aa[j]==c[i])
                        {
                            swap(aa[i],aa[j]);
                            ans++;
                            break;
                        }
                        else
                        {
                            swap(aa[i],aa[j]);
                            ans++;
                        }
                    }
                }
            }
        }
        cout<<ans<<endl;

    }
    return 0;
}

B - Miscalculation

Sample Input
1+2*3+4
11
1+2*3+4
13
3
3
1+2*3+4
9
Sample Output
M
L
U
I

题意:给出一个只含有乘除的表达式,有两种方式计算它的值,第一种先做乘法,后做加法,第二种从前往后做,不考虑符号的优先级,在给出一个数n,如果n的值与第一种方法计算的值相等,输出M;如果与第二种计算方法相等,输出L,都相等输出U,都不相等,输出I。关键就是表达式求值。不考虑优先级的比较简单。本题关键就是表达式求值。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=1E9+7;;
const int MM=192600817;
deque <char> q;
deque <ll> q2;
string s;
int f()
{
    while(!q.empty())
    {
        char t=q.front();
        if(t>='0'&&t<='9')
        {
            q2.push_back(t-'0');
            q.pop_front();
        }
        else if(t=='+')
        {
            q.pop_front();
        }
        else if(t=='*')
        {
            ll a,b,ans;
            char m;
            int mm;
            q.pop_front();
            m=q.front();
            b=m-'0';
            q.pop_front();

            mm=q2.back();
            q2.pop_back();
            a=mm;

            ans=a*b;
            q2.push_back(ans);

        }
    }
    ll ans=0;
    while(!q2.empty())
    {
        ll tt=q2.front();
            ans+=tt;
        q2.pop_front();
    }
    return ans;
}
int main()
{
    ll n,m,e,i,j,x,ans=0;
    char c;
    while(cin>>s)
    {
        ll ans1=0,ans2=0;
        ll len=s.size();
        ll flag=0;
        ans1=s[0]-'0';
        ll sum=0;
        for(i=1; i<len; i++)//从前往后计算表达式
        {
            if(s[i]>='0'&&s[i]<='9')
            {
                if(c=='+')
                    ans1+=(s[i]-'0');
                else if(c=='*')
                    ans1*=(s[i]-'0');
            }
            else if(s[i]=='+')
                c=s[i];
            else if(s[i]=='*')
            {
                c=s[i];
                sum++;
            }
        }
        if(sum==len/2)//特判一下全是乘法的情况
        {
            ans2=1;
            for(i=0;i<len;i++)
            {
                if(s[i]>='0'&&s[i]<='9')
                    ans2*=s[i]-'0';
            }
        }
        else//考虑优先级的表达式的求法
        {
          //先把表达式放到1号队列当中,如果不是“×”,就放到2号队列当中,如果是乘号,
          //就在2号队列的后面取出一个数,在1号队列前面取出一个数,相乘的结果放到2
          //号队列的后面。最后将2号队列里面的数相加。注意char和int类型的转换!
            while(!q.empty())
                q.pop_front();
            while(!q2.empty())
                q.pop_front();
            for(i=0; i<len; i++)
            {
                q.push_back(s[i]);
            }
            ans2=0;
            ans2=f();
        }
        cin>>n;
        if(n==ans1&&n==ans2)
            cout<<"U"<<endl;
        else if(n==ans1)
            cout<<"L"<<endl;
        else if(n==ans2)
            cout<<"M"<<endl;
        else
            cout<<"I"<<endl;
    }
    return 0;
}

 

以上是比赛过程中做出来的。

C  Shopping

Sample Input
10 3
3 7
8 9
2 5
10 3
8 9
6 7
2 4
10 0
10 6
6 7
4 5
2 5
6 9
3 5
6 8
1000 8
3 4
6 1000
5 1000
7 1000
8 1000
4 1000
9 1000
1 2
Sample Output
23
19
11
23
2997

 题意:要去逛商场,商店是从1到n编号的,按顺序排成一列,然后给一些数(a,b)代表到b商店时必须回到a商店在买一些东西,每个相邻的商店长度为1,出口在n+1的位置上,问,到出口走的最短的长度是多少。

思路:最短的长度是当m等于0时,长度为n+1.用贪心的思想,例如第一组样例,可以走的路线是1->2->7->2->7->出口。其实就是将2 5和3 7改成2 7即可,注意会有一次覆盖多种的情况,将5改成7之后标记一下2 7,2 7以后就用不到了。然后把所有没标记的(y-x)*2相加,最后加上初始值11.

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=1E9+7;;
const int MM=192600817;
deque <char> q;
string s;
ll flag[550]={0};
struct AA
{
    ll x;
    ll y;
}aa[550];
bool cmp(struct AA p,struct AA q)
{
    if(p.x==q.x)
        return p.y<q.y;
    return p.x<q.x;
}
int main()
{
    ll n,m,i,j,k,a,b;
    while(cin>>n>>m)
    {
        memset(flag,0,sizeof(flag));
        for(i=0;i<m;i++)
        {
            cin>>aa[i].x>>aa[i].y;
        }
        ll ans=n+1;
        sort(aa,aa+m,cmp);
        for(i=0;i<m;i++)
        {
            if(flag[i]==1)
                continue;
            ll rr=aa[i].y;
            for(j=i+1;j<m;j++)
            {
                if(aa[j].x<=rr)
                {
                    rr=max(aa[j].y,rr);//括号里一定是rr,如果写成aa[i].y不对,因为rr在变
                    flag[j]=1;
                }
                else//没必要一直循环下去
                {
                    break;
                }
            }
            aa[i].y=rr;//最后将aa[i].y更改
        }
        for(i=0;i<m;i++)
        {
            if(flag[i]==0)
            {
                ans+=2*(aa[i].y-aa[i].x);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值