2020CSP-J普及组复赛

https://ac.nowcoder.com/acm/contest/8848#question

A-优秀的拆分(power)

解法一:
任意一个自然数都可以拆分成若干个不同的2的幂次方的和,比如1100010100,相当于1不断向左移,而1向左移动一位就相当于乘2,题目说是正整次幂,所有二进制第一位不能为一,否则会加一,不和题意。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e4+7;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

int main()
{
	int n,res = 1;
	int a[55],t = 0;
	cin >> n;
	if(n & 1) cout << "-1";
	else{
        while(n){
        	if(n&1) a[t++] = res;
        	res <<= 1;
        	n >>= 1;
    	}
    	for(int i = t-1; i >= 0; i--){
	    	cout << a[i] << " ";
    	} 
    }
	return 0;
}
解法二:先找出1-1e7中2幂次数有哪些,然后从后往前取

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e4+7;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

int cnt = 0;
int a[55],n,vis[55],b[5500];
void init()
{
	ll res = 2;
	a[cnt++] = 2;
	while(res <= 1e7){
		res *= 2;
		a[cnt++] = res;
	}
}

int main()
{
	init();
	cin >> n;
	if(n & 1) cout << "-1";
	else{
		int t = 0;
	    for(int i = cnt-1; i >= 0; i--){
	        if(n >= a[i]) {
	        	b[t++] = a[i];
	            n -= a[i];
			}
	    }
	        for(int i = 0; i < t; i++){
	        	cout << b[i] << " ";
	    }
	}
	return 0;
}
解法三:DFS搜索,因为只有24个数,DFS+剪枝可以满足

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e4+7;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

int cnt = 0;
int a[55],n,vis[55];
void init()
{
	ll res = 2;
	a[cnt++] = 2;
	while(res <= 1e7){
		res *= 2;
		a[cnt++] = res;
	}
}

int flag = 0;
int b[55];
void dfs(int res,int xb)
{
	//cout << res << endl;
	if((res <= 1 && res != 0) || flag == 1){
		return;
	}
	if(res == 0){
		flag = 1;
		int t = 0;
		for(int i = 0; i < cnt; i++){
			if(vis[i]) b[t++] = a[i];
		//	cout << i << " ";
		} 
		sort(b,b+t);
		for(int i = t-1; i >= 0; i--){
			cout << b[i] << " ";
		} 
		return;
	}
	for(int i = 0; i < xb; i++){//因为先去了xb之后的数,接下来要取的数只能是1-xb-1 之间的数,这一步缺少会超时。
		if(vis[i] || res < a[i]) continue;
		vis[i] = 1;
		dfs(res-a[i],i);
		vis[i] = 0;
	}
}

int main()
{
	init();
	cin >> n;
	dfs(n,cnt-1);
	if(!flag) cout << "-1" << endl;
	return 0;
}

B-直播获奖

思路:大根堆+小根堆,一般两者是在一起使用的。大根堆在左,小根堆在右,用小根堆的大小去维护获奖人数,每次输出小根堆的堆顶元素。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

priority_queue<int,vector<int>,less<int> >q1;//大根堆 
priority_queue<int,vector<int>, greater<int> >q2;//小根堆 
int b[1000005];
int main()
{
	int num = 0,n,w,x;
	scanf("%d%d",&n,&w);
	for(int i = 1; i <= n; i++){
		scanf("%d",&x);
		int hj_num = i*w/100;
		hj_num = max(1,hj_num);
		if((!q2.empty() && q2.top() <= x) || q2.empty()){
			q2.push(x);
		}
		else q1.push(x);
		while(q2.size() < hj_num){
			int temp = q1.top();
			q1.pop();
			q2.push(temp);
		}
		while(q2.size() > hj_num){
			int temp = q2.top();
			q2.pop();
			q1.push(temp);
		}
		printf("%d ",q2.top());
	} 
	return 0;	
} 



D-放格取数:动态规划

dfs超时代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e4+7;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

struct node{
	int x,y;
	node(int a,int b){
		x = a;
		y = b;
	}
};

int dir[3][2] = {{-1,0},{1,0},{0,1}};
int vis[10005][10005];
ll a[10005][10005] = {0},ans = -ds;
int n,m;
bool check(int x,int y)
{
	if(x <= 0 || x > n || y <= 0 || y > m) return false;
	return true;
}

void dfs(int x,int y,ll l)
{
	//cout << l <<endl;
//	cout << x << y << endl;
	if(x == n && y == m){
		ans = max(l,ans);
	//	cout << ans << endl;
		return;
	}
	for(int i = 0; i < 3; i++){
		int dx = x + dir[i][0];
		int dy = y + dir[i][1];
	//	cout << dx << dy << endl;
		if(vis[dx][dy]) continue;
		if(check(dx,dy)){
	    	vis[dx][dy] = 1;
	    	dfs(dx,dy,1ll*(l+a[dx][dy]));
	    	vis[dx][dy] = 0;
	    }
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			scanf("%lld",&a[i][j]);
		}
	}
	vis[1][1] = 1;
	dfs(1,1,a[1][1]);
	printf("%lld\n",ans);
	return 0;
}

动态规划:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#include <list>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;

using namespace std;

int n,m;
ll dp[1005][1005][2],a[1005][1005];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			scanf("%lld",&a[i][j]);
		}
	}
    memset(dp, -0x3f, sizeof dp);
	dp[1][0][0] = 0;
	for(int j = 1; j <= m; j++){
		for(int i = 1; i <= n; i++){
			dp[i][j][0] = max(dp[i-1][j][0],max(dp[i][j-1][1],dp[i][j-1][0])) + a[i][j];
		}
		for(int i = n; i >= 1; i--){
			dp[i][j][1] = max(dp[i+1][j][1],max(dp[i][j-1][0],dp[i][j-1][1])) + a[i][j];
		}
	}
	printf("%lld",max(dp[n][m][1],dp[n][m][0]));
	return 0;	
} 

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-20 19:57
已编辑
某大厂 golang工程师 23.0k*16.0, 2k房补,年终大概率能拿到
点赞 评论 收藏
分享
11-05 07:29
贵州大学 Java
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务