牛客算法入门题单

矩阵消除游戏

矩阵消除游戏

首先用n位二进制表示n行里面哪些行是被挑走了,哪些是留着的,对这个二进制遍历,九八所有n行的可能结果就遍历出来,然后去把每一情况下的剩下的列的和从大到小排列,然后就先看行呗挑走的数量,然后k-这个数就是lie的数量,从大到小贪心吃这个数量。即可,注意特殊情况判断(k>=m||k>=n).然后直接用数组需要每次挑行的时候都重新赋值为0,不然会出问题,vector也一样用fill重新赋值。

//vector版
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
typedef long long ll;
//int sm[N],ps[N];
int n,m,k,cnt;
vector<vector<int>> v(20,vector<int>(20));
vector<int>lie(20,0);
bool cmp(int a,int b)
{
	return a>b;
}
int calc(int x)
{
	int sum2=0;
	for(int i=1;i<=n;i++)
	{
		if(((x>>(i-1))&1)==1)
		{
			for(int j=1;j<=m;j++)
			{sum2+=v[i][j];}
			cnt++;
		}
		else {
			for(int j=1;j<=m;j++)
			{
				lie[j]+=v[i][j];
			}
		}
	}
	return sum2;
}
void solve() {
	cin>>n>>m>>k;int sum1=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			{cin>>v[i][j];sum1+=v[i][j];}
		//cout<<sum1<<endl;
	if(k>=m||k>=n){cout<<sum1<<endl;return ;}
	int ans=0;
	for(int i=0;i<=(1<<n)-1;i++)
	{
		//memset(lie,0,sizeof(lie));
        fill(lie.begin(), lie.end(), 0);
		cnt=0;
		int sum2=calc(i);
		sort(lie.begin()+1,lie.begin()+1+m,cmp);
		//for(int q=1;q<=m;q++)cout<<lie[q]<<" ";
		if(cnt<=k)
		{
			int rest=k-cnt;
			for(int j=1;j<=rest;j++)
			{
				sum2+=lie[j];
			}
		}
		else continue;
		ans=max(sum2,ans);
	}
	cout<<ans<<endl;
}
int main(){    
        solve();    
    return 0;
}
//int版
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
typedef long long ll;
//int sm[N],ps[N];
int n,m,k,cnt;
int v[20][20];
int lie[20];
bool cmp(int a,int b)
{
	return a>b;
}
int calc(int x)
{
	int sum2=0;
	for(int i=1;i<=n;i++)
	{
		if(((x>>(i-1))&1)==1)
		{
			for(int j=1;j<=m;j++)
			{sum2+=v[i][j];}
			cnt++;
		}
		else {
			for(int j=1;j<=m;j++)
			{
				lie[j]+=v[i][j];
			}
		}
	}
	return sum2;
}
void solve() {
	cin>>n>>m>>k;int sum1=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			{cin>>v[i][j];sum1+=v[i][j];}
		//cout<<sum1<<endl;
	if(k>=m||k>=n){cout<<sum1<<endl;return ;}
	int ans=0;
	for(int i=0;i<=(1<<n)-1;i++)
	{
		memset(lie,0,sizeof(lie));
		cnt=0;
		int sum2=calc(i);
		sort(lie+1,lie+1+m);
		if(cnt<=k)
		{
			int rest=k-cnt;
			for(int s=1,j=m;s<=rest;j--,s++)
			{
				sum2+=lie[j];
			}
		}
		else continue;
		ans=max(sum2,ans);
	}
	cout<<ans<<endl;
}
int main(){    
        solve();    
    return 0;
}

华华听月月唱歌

题目链接

贪心,sort按第一主键从小到大排序,,这里使用结构体或者其他都行。然后贪婪地往r值大的取找,在所有比前一个r+1小的l的对应的r要尽量大。然后注意特判,一个是看是不是小于r+1(是不是连续的区间)还有一个是如果最右大于n了,就超长度了,那就break掉,

#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
typedef long long ll;
struct NODE
{
	int l;
	int r;
}node[N];
bool cmp(NODE n1,NODE n2)
{
	if(n1.l==n2.l) return n1.r>n2.r;
	return n1.l<n2.l;
}
int main(){    
    int m,n,flag=1;cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
    	cin>>node[i].l>>node[i].r;
    }
    sort(node+1,node+1+m,cmp);
    int cnt=1,l=0,r=0;
    	for(int i=1;i<=m;i++)
    	{
    		if(node[i].l<=l+1)
    		{
    			r=max(r,node[i].r);
    		}
    		else 
    		{
    			l=r;
    			if(node[i].l>l+1){cnt=-1;break;}
    			else
    			{
    				cnt++;
    				r=max(r,node[i].r);
    			}    		
    		}
            if(r>=n)break;
    	}
    if(r<n)cnt=-1;
    cout<<cnt<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值