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

输入

(n <= 100 ai <= 10000,ai之和<=10000)

样例输入

1
3
1
10

样例输出

3
11

提示

#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);

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120