【01背包】小刷上学记 校OJ2236

题目描述

有n个小朋友一起结伴同行去上学,每个小朋友的口袋里都有一些糖果,孩子的世界总是单纯而又可爱,现在其中的小刷提出了一个问题,如果把某些人(大于等于1个人)的糖果组合起来,能否组合出素数个糖果呢?如果能够组合出素数个糖果,能组成的最大的素数又是多少呢?如果不能,又最接近于哪个素数呢?如果一样接近,最大的又是哪个素数呢?
看,小刷的世界就是这么单洁而又可爱!

输入

第一行输入一个n,紧接着下一行输入n个整数ai表示n个小朋友口袋里的糖果。
(n <= 100 ai <= 10000,ai之和<=10000)

输出

对于每组数据,输出一个数answer,表示能组合出来的最大的素数,如果不能组合出素数, 输出能组合出来的最接近的素数,如果有多个,输出最大的那个。即满足abs(answer - i)是最小的,且answer最大。( i是能通过若干个小朋友组合出来的糖果数量)输出的素数小于10000

样例输入

1
3
1
10

样例输出

3
11

提示


输出的素数小于10000


#include <bits/stdc++.h>
using namespace std;

int n;
int a[110];
int pri[2000];
bool dp[10010];
int can[10010];

bool prime (int x) //判定素数
{
	for (int i = 2; i * i <= x; i++)
		if (x % i == 0) return 0;
	return 1;
}

int main()
{
	int T = -1;
	for (int i = 2; i <= 10000; i++)
	{
		if (prime(i))
		{
			T++;
			pri[T] = i;
		}
	}  //将素数从小到大存进pri数组中

	while (~scanf ("%d", &n))
	{
		int total = 0;
		for (int i = 0; i < n; i++)
		{
			scanf ("%d", &a[i]);
			total += a[i];
		}

		memset (dp, 0, sizeof (dp));
		dp[0] = 1;

		int Q = -1;
		for (int i = 0; i < n; i++)
		{
			for (int j = total; j >= a[i]; j--)
			{
				if (dp[j - a[i]] && dp[j] == 0)
					//dp[j]==0 保证can中无重复
				{
					dp[j] = 1;
					can[++Q] = j;
				}
			}
		}

		sort (can, can + Q + 1, less<int>() ); //从小到大

		int minn = 1e9;
		int ans = -1;
		int t = lower_bound (pri, pri + T + 1, total) - pri;

		for (int i = min (t, 1228); i >= 0; i --) //从大到小
		{
			int g = pri[i];
			int p = lower_bound (can, can + Q + 1, g) - can;
			//p = min (p, 1228);    p在can上 无限制
			int u;
			if (p == 0) u = abs (g - can[p]);
			else if(p == Q+1) u = abs(g - can[p-1]);
			else u = min (abs (g - can[p]), abs (g - can[p - 1]) );
			if (minn > u)
			{
				minn = u;
				ans = g;
			}
		}
		printf ("%d\n", ans);
	}
	return 0;
}
		for (int i = 0; i < 10010; i++)
		{
			L[i] = 1e9;
			R[i] = 1e9;
		}

		for (int i = 1; i <= 10000; i++)
		{
			if (dp[i]) //i可被组成
				L[i] = i;
			else
				L[i] = L[i - 1];
		}

		for (int i = 10000; i >= 0; i--)
		{
			if (dp[i])
				R[i] = i;
			else
				R[i] = R[i + 1];
		}

		int mminn = 1e9;
		int res = -1;
		for (int i = T; i >= 0; i--)
		{
			int q = pri[i];
			int u = min (abs (q - L[q]), abs (q - R[q]) );
			if (mminn > u)
			{
				mminn = u;
				res = pri[i];
			}
		}
		printf ("%d\n", res);



猜你喜欢

转载自blog.csdn.net/ummmmm/article/details/80350498
今日推荐