刷题记录(NC200190 矩阵消除游戏,NC23036 华华听月月唱歌)

NC200190 矩阵消除游戏

题目链接

关键点: 

1、因为无论行和列的选择会相互影响,所以不能直接利用贪心,要将行列分开选。

2、先选行,因为最大有20行,利用二进制的01来表示当前所选的行,1表示选择该行

3、接下来跟据所选的行对原数组进行选中的行的值求和,对于没选中的行,将其加入列数组里,因为选择的行在算列时,已经被删除。

4、将列数组进行排序,并倒着(从小到大排序)选择大的求和

5、细节:如果当前可以选的k大于行数或者列数(n和m),那么直接输出所有数的和

6、细节:算好选择行数时,要判断剩余给列选择的数是否大于0

完整代码:

# include <iostream>
# include <algorithm>
# include <cstring>
using namespace std;
int n, m, k;
int a[20][20];
int lie[20];
int cnt, ans;
int calc(int x)
{
    int total=0;
    cnt=0;
    for (int i=1; i<=n; i++)
    {
        if ((x>>(i-1))&1==1)
        {
            for (int j=1; j<=m ; j++)
            total+=a[i][j];
            cnt++;
        }
        else
        {
            for (int j=1; j<=m; j++)
            {
                lie[j]+=a[i][j];
            }
        }
    }
    return total;
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    int sum=0;
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=m; j++)
        {
            scanf("%d", &a[i][j]);
            sum+=a[i][j];
        }
    }
    if (k>=n||k>=m)
    {
        cout<<sum<<endl;
        return 0;
    }
    for (int i=0; i<=(1<<n)-1; i++)
    {
        memset(lie, 0, sizeof(lie));
        sum = calc(i);
        int res = k-cnt;
        if (res<0)
            continue;
        sort(lie+1, lie+1+m);
        for (int j=m; j>=1&&res; res--,j--)
        {
            sum+=lie[j];
        }
        ans = max(ans, sum);
    }
    cout<<ans;
    
    
    return 0;
}

NC23036 华华听月月唱歌

题目链接

关键点: 

1、将区间数据按照第一关键字:起始点(从小到大),第二关键字:结尾(从大到小)排序

2、设出初始的l,r值为1,之后进行更新,如果当前的起始点会小于等于l,那么更新r的最大值,如果不满足,那么总数加1,l=r+1,再次判断当前结点

3、因为这样判断会把最后一个数的个数给忽略,所以初始值的个数从1开始

完整代码:

# include <iostream>
# include <algorithm>
# include <cstdio>
# include <set>
using namespace std;
int n, m;
struct ty{
    int start;
    int end;
}t[100000+10], t2[100000+10];
set<int>s;
bool cmp(ty t1, ty t2)
{
    if (t1.start!=t2.start)
        return t1.start<t2.start;
    else
    return t1.end>t2.end;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i=1; i<=m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        t[i].start = x;
        t[i].end = y;
    }
    sort(t+1, t+1+m, cmp);
    int l = 1;
    int r = 1;
    if (l!=1)
    {
        cout<<"-1";
        return 0;
    }
    int total=1;
    for (int i=1; i<=m; i++)
    {
    	if (t[i].start<=l)
    	r = max(r, t[i].end);
    	else
    	{
    		total++;
    		l = r+1;
    		if (t[i].start<=l)
    		r = max(t[i].end, r);
    		else
    		{
    			cout<<"-1";
    			return 0;
			}
		}
		if (r>=n)
		break;
	}
	if (r>=n)
	cout<<total;
	else
	cout<<"-1";
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值