ShanDong Multi-University Training #1

A(贪心)

A - A

题意:共有n种牌,接下来n行,第i行一个整数Ai表示号码为i的牌有Ai张,当两张牌号码的绝对值小于等于1时,就可以凑成一对,问最多可以凑成几对。

思路:当牌数为偶数时,就与号码一样的配对,当牌数为奇数时,就用掉一张下一个号码的牌来配对。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
int n;
void solve()
{
    cin>>n;
    vector <int> a(n+1);
    for(int i = 1 ; i <= n ; i++)
    {
        cin>>a[i];
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++)
    {
        if(a[i]&1)
        {
            ans+=a[i]/2;
            if(a[i+1]!=0) 
            {
                a[i+1]--;
                ans++;
            }
        }
        else 
        {
            ans+=a[i]/2;
        }
    }
    cout<<ans<<'\n';
}
int main()
{
    //ios;
    int _t=1;
    //cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

B(思维)

B - B

题意:起初有1克金子,0克银子,在接下来的n天里,每天有一个汇率x,可以A克金子换成xA的银子,也可以将A的银子换成A/x的金子,或者不进行交换。给出接下来n天的汇率,问如何交换可以获得最多的金子

思路:将每天的汇率画成函数图,则一定在高峰换银子,低谷换金子。注意最后一次要换成金子,当交换次数为奇数时,去掉最后一次交换即可

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
int n;
void solve()
{
    cin>>n;
    vector<int>a(n+2);
    vector<int>ans(n+2);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    a[n+1]=a[n]+1;
    int flag=0;
    int cnt=0;
    for(int i = 1 ;i <= n;i ++)
    {
        if(flag == 0 && a[i] >= a[i-1]&&a[i] >= a[i+1])
        {
            flag = 1;
            ans[i] = 1;
            cnt++;
        }
        else if(flag == 1 && a[i] <= a[i-1] && a[i] <= a[i+1])
        {
            flag=0;
            ans[i]=1;
            cnt++;
        }
    }
    if(cnt&1)
    {
        for(int i = n; i >= 1; i--)
        {
            if(ans[i])
            {
                ans[i]=0;
                break;
            }
        }
    }

    for(int i = 1; i<= n; i++)
    {
        cout<<ans[i]<<" \n"[i==n];
    }

}
int main()
{
    //ios;
    int _t=1;
    //cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

M(思维)

M - M

题意:给你四种字符串“((" , "()" , ")(" , "))"的个数a,b,c,d。问能否拼出合法序列

思路:第二种不用管。第一种和第四种的个数一定要相等才能使左右括号个数相等。第三种放在序列中间即可,会消耗掉一个左括号一个右括号。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
int a,b,c,d;
void solve()
{
    cin>>a>>b>>c>>d;

    if(a == d && a>0)
    {
        cout<<1<<'\n';
        return ;
    }
    if(a == d && a==0 && c==0)
    {
        cout<<1<<'\n';
        return ;
    }
    cout<<0<<'\n';
}
int main()
{
    //ios;
    int _t=1;
    //cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

E(思维)

E - E

题意:一个A*B*C的长方体由1*1*1的小长方体组成,问如何将大长方体分成两个小长方体,使两个小长方体的体积差最小。

思路:当有一条边为偶数时,从中点对半分,差值最小为0。当三条边都是奇数时,切分后两个小长方体的体积总是差一排小长方体,要使体积差最小,只需从A*B,A*C,B*C中取最小。

所以,答案就是三个边中的一个边%2与另外两个边的乘积,最后取三种情况的最小值,简洁明了。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
ll a,b,c;
void solve()
{
    cin>>a>>b>>c;
    ll ans=min((a%2)*b*c,min((b%2)*a*c,(c%2)*a*b));
    cout<<ans<<'\n';
}
int main()
{
    //ios;
    int _t=1;
    //cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

K(博弈)

K - K

题意:有n个节点的无根树,其中有一个特殊节点x,给出n-1条边。每次操作可以删除一个叶子节点及其边,谁删除特殊节点x谁获胜,Ayush先手,问谁会获胜。

思路:当x为叶子节点时,先手胜。否则,选择x为根重构这棵树,二者都是先删除叶子节点,

 直至x的每棵子树只剩一个节点时。

然后二者删除x的儿子节点,直至x的度为1时(只剩一条边时),下一位玩家获胜。

此过程中,共删除了n-2条边,只需讨论n-2或n的奇偶即可。当n为偶数时, Ayush胜;n为奇数时,Ashish胜

注意特判当n等于1时,Ayush胜。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
int n,x;
void solve()
{
    cin>>n>>x;
    if(n == 1)
    {
        cout<<"Ayush\n";
        return ;
    }
    int cnt=0;
    for(int i = 1; i <= n-1 ; i++)
    {
        int u,v;
        cin>>u>>v;
        if( u == x || v == x ) cnt++;
    }
    if(cnt == 1 || n%2 == 0) cout<<"Ayush\n";
    else cout<<"Ashish\n";
}
int main()
{
    //ios;
    int _t=1;
    cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

H

H - H

题意:有一个h*w的矩阵,在矩阵的每个格上有两个数Ai和Bi,可以选择将一个涂成红色,另一个就被涂成蓝色。现在从(1,1)移动到(h,w),只能向下或向右移动,求最后走到(h,w)时路径上蓝色总值与红色总值差的绝对值最小是多少

思路:bool型dp[i][j][k]表示在位置(i,j)时,路径上蓝红差值k能否取到。则它是由上面位置和左面位置转移过来。由于Ai,Bi∈[0,80],h,w∈[2,80]所以路径上差值最大为(h+w-1)*80.由于差值可为负,为避免数组越界可以将k数组开到12800*2,用k与12800的差值表示路径上差值。

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;

using namespace std;
bool dp[85][85][12810*2];
int h,w;
int a[85][85],b[85][85],d[85][85];
void solve()
{
    cin >> h >> w;
    for(int i = 1; i <= h; i++)
        for(int j = 1; j <= w; j++)
            cin >> a[i][j];
    for(int i = 1; i <= h; i++)
        for(int j = 1; j <= w; j++)
        {
            cin >> b[i][j];
            d[i][j] = a[i][j] - b[i][j];
        }

    dp[1][1][12800+d[1][1]] = 1;
    dp[1][1][12800-d[1][1]] = 1;
    for(int i = 1; i <= h ; i++)
    {   
        for(int j = 1;j <= w; j++)
        {
            if(i == 1 && j == 1) continue;
            for(int k = 0; k <= 12800*2; k++)
            {
                int tem1=d[i][j];
                int tem2=-d[i][j];
                dp[i][j][k]=dp[i-1][j][k-tem1]||dp[i-1][j][k-tem2]||dp[i][j-1][k-tem1]||dp[i][j-1][k-tem2];
            }
        }
    }        
    int ans=inf;
    for(int i = 0; i <= 12800*2; i++)
    {
        if(dp[h][w][i])
        {
            ans=min(ans,abs(i-12800));
        }
    }
    cout<<ans<<'\n';
}
int main()
{
    //ios;
    int _t=1;
    //cin>>_t;
    while(_t--)
    {
        solve();
    }
    system("pause");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值