1.平分物品
现在有n个物品,每一个物品都有一个价值,现在想将这些物品分给两个人,要求这两个人每一个人分到的物品的价值总和相同(个数可以不同,总价值相同即可),剩下的物品就需要扔掉,现在想知道最少需要扔多少价值的物品才能满足要求分给两个人。
输入描述:
第一行输入一个整数 T,代表有 T 组测试数据。
对于每一组测试数据,一行输入一个整数 n ,代表物品的个数。
接下来 n 个数,a[i] 代表每一个物品的价值。
1<= T <= 10
1 <= n <= 15
1 <= a[i] <= 100000
输出描述:
对于每一组测试数据,输出一个答案代表最少需要扔的价值。
输入例子1:
1 5 30 60 5 15 30
输出例子1:
20
例子说明1:
样例解释,扔掉第三个和第四个物品,然后将第一个物品和第五个物品给第一个人,第二个物品给第二个人,每一个人分到的价值为60,扔掉的价值为20。
题解:暴力DFS,居然过了(写的很丑 不够优雅)
#include <iostream>
#define MAXINT 0x3f3f3f3f
using namespace std;
int sum1, sum2, all, n, ans;
int a[20];
void solve(int num)
{
if (sum1 == sum2) {
int tmp = all - (sum1+sum2);
ans = ans < tmp ? ans : tmp;
}
if (num == n) return;
sum1 += a[num];
solve(num+1);
sum1 -= a[num];
sum2 += a[num];
solve(num+1);
sum2 -= a[num];
solve(num+1);
}
int main()
{
int t;
cin >> t;
while (t--) {
cin >> n;
ans = MAXINT;
all = 0;
sum1 = sum2 = 0;
for (int i = 0; i < n; ++i) {
cin >> a[i];
all += a[i];
}
sum1 += a[0];
solve(1);
sum1 -= a[0];
sum2 += a[0];
solve(1);
sum2 -= a[0];
solve(1);
cout << ans << endl;
}
return 0;
}
2.买票问题
现在有n个人排队买票,已知是早上8点开始卖票,这n个人买票有两种方式:
第一种是每一个人都可以单独去买自己的票,第 i 个人花费 a[i] 秒。
第二种是每一个人都可以选择和自己后面的人一起买票,第 i 个人和第 i+1 个人一共花费 b[i] 秒。
最后一个人只能和前面的人一起买票或单独买票。
由于卖票的地方想早些关门,所以他想知道他最早几点可以关门,请输出一个时间格式形如:08:00:40 am/pm
时间的数字要保持 2 位,若是上午结束,是 am ,下午结束是 pm
输入描述:
第一行输入一个整数 T,接下来有 T 组测试数据。
对于每一组测试数据:输入一个数 n,代表有 n 个人买票。
接下来n个数,代表每一个人单独买票的时间 a[i]。
接下来 n-1 个数,代表每一个人和他前面那个人一起买票需要的时间 b[i]
1<= T <=100
1<= n <=2000
1<= a[i] <=50
1<= b[i] <=50
输出描述:
对于每组数据,输出一个时间,代表关门的时间 。
输入例子1:
2 2 20 25 40 1 8
输出例子1:
08:00:40 am 08:00:08 am
题解:简单DP,每次判断当前这个人是和前面的结合起来买票更快还是自己买票更快,需要注意的是,如果当前这个人和前面的人一起买票,那么前面的人就不能和再前面的人一起买票了,所以是dp[i] = min(dp[i-1]+a[i], dp[i-2]+b[i])。反倒是换成时间挺难的。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int T, n;
int a[2005], b[2005];
int dp[2005];
cin >> T;
while (T--) {
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
for (int i = 1; i < n; ++i) cin >> b[i];
if (n == 1) {
int hour = 8;
int mins = 0;
int sec = a[0];
mins += a[0]/60;
sec = a[0]%60;
hour += mins/60;
mins = mins%60;
bool am = true;
if (hour > 12) {
am = false;
hour = hour%12;
}
if (hour < 10) cout << "0";
cout << hour << ":";
if (mins == 0) cout << "00";
else {
if (mins < 10) cout << "0" << mins;
else cout << mins;
}
cout << ":";
if (sec == 0) cout << "00";
else {
if (sec < 10) cout << "0" << sec;
else cout << sec;
}
if (am) cout << " am\n";
else cout << " pm\n";
continue;
}
dp[0] = a[0];
dp[1] = b[1] < (a[0]+a[1]) ? b[1] : (a[0]+a[1]);
for (int i = 2; i < n; ++i) {
dp[i] = min(dp[i-1]+a[i], dp[i-2]+b[i]);
}
int time = dp[n-1];
int hour = 8;
int mins = 0;
int sec = time;
mins += time/60;
sec = time%60;
hour += mins/60;
mins = mins%60;
bool am = true;
if (hour > 12) {
am = false;
hour = hour%12;
}
if (hour < 10) cout << "0";
cout << hour << ":";
if (mins == 0) cout << "00";
else {
if (mins < 10) cout << "0" << mins;
else cout << mins;
}
cout << ":";
if (sec == 0) cout << "00";
else {
if (sec < 10) cout << "0" << sec;
else cout << sec;
}
if (am) cout << " am\n";
else cout << " pm\n";
}
return 0;
}
3.小易爱回文
小易得到了一个仅包含大小写英文字符的字符串,该字符串可能不是回文串。(“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串,“asds”就不是回文串。)
小易可以在字符串尾部加入任意数量的任意字符,使其字符串变成回文串。
现在请你编写一个程序,程序要能计算出小易可以得到的最短回文串。
输入描述:
一行包括一个字符串。长度为[1, 1000]
输出描述:
一行包括一个字符串,代表答案。
输入例子1:
noon
输出例子1:
noon
输入例子2:
noo
输出例子2:
noon
输入例子3:
helloworld
输出例子3:
helloworldlrowolleh
题解:还是暴力法,先判断是不是回文,是的话就输出。因为要找最短的,所以不是的话检查后n个字符是否为回文串,是的话,生成的回文串就是字符串本体+前len-n个字符的倒序。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
cin >> str;
bool flag = true;
int len = str.length();
for (int i = 0; i < len/2; ++i) {
if (str[i] != str[len-i-1]) {
flag = false;
break;
}
}
if (flag) cout << str << endl;
else {
for (int i = 0; i < len; ++i) {
string tmp = str.substr(i, len-i);
bool flagTmp = true;
int lenTmp = tmp.length();
for (int i = 0; i < lenTmp/2; ++i) {
if (tmp[i] != tmp[lenTmp-i-1]) {
flagTmp = false;
break;
}
}
if (flagTmp) {
cout << str;
string ans = str.substr(0, len-lenTmp);
int lenAns = ans.length();
for (int i = lenAns-1; i >= 0; --i) {
cout << ans[i];
}
cout << "\n";
break;
}
}
}
return 0;
}
4.素数个数
牛牛现在有一个包含 n 个正整数的数组 a ,牛牛可以将其中的每个数 a[i] 都拆成若干个和为 a[i] 的正整数,牛牛想知道拆后(也可以一个数都不拆)这个数组最多能有多少个素数。
输入描述:
第一行一个正整数 n 代表数组长度
第二行 n 个正整数代表 a[i] 的值
1<= n <= 1e^6, 1<= a[i] <= 1e^9
输出描述:
拆后数组最多的素数个数
输入例子1:
3 1 1 1
输出例子1:
0
例子说明1:
由于1不能再拆,并且1不是素数,所以拆后最多有0个素数
输入例子2:
3 5 3 7
输出例子2:
6
例子说明2:
3不拆;5可以拆成{2,3},变成2个素数;7可以拆成{2,2,3},变成3个素数,所以最后拆后数组最多有6个素数
题解:其实就是把数字拆分为2和3,这是素数最多的拆分情况,所以只需要计算有多少个2,因为3的话也是2+1。
卡在没想到数据的范围能有long long那么大。
#include <iostream>
using namespace std;
int a[1000000+5];
int main()
{
int n;
long long ans = 0;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> a[i];
if (a[i] < 2) continue;
ans += (a[i]/2);
//if (a[i] % 2 == 1) ans++;
}
cout << ans << endl;
return 0;
}