双核处理
一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述 :
输入包括两行:
第一行为整数n(1 ≤ n ≤ 50)
第二行为n个整数length[i](1024 ≤ length[i] ≤ 4194304),表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述 :
输出一个整数,表示最少需要处理的时间
输入例子 :
5
3072 3072 7168 3072 1024
输出例子 :
9216
思考:这道题大致意思是把这些任务分为两部分,分别有两个cpu处理, 最小时间取决于处理时间相当对长的那个cpu所消耗的时间。目录是把数据分为两部分, 这两部分的和的差值最小!利用01背包可以解此题,下面分别用一维和二维数组实现。
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 55;
int w[maxn];//背包的容量和价值相等
int n;//n个物品
int W = 0;//背包容量
int dp[maxn][5000*25];
int DP() {
int Size = W/2;
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= Size; j++) {
if(j < w[i]) {
dp[i][j] = dp[i-1][j];
} else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + w[i]);
}
}
}
return dp[n][Size];
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
w[i] /= 1024;
W += w[i];
}
int res = DP();
cout << max(res, W-res) * 1024 << endl;
return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 55;
int n;//n个物品
int f[5000*25];
int w[maxn];//背包的容量和价值相等
int W = 0;//背包容量
int DP() {
int half = W/2;
for(int i = 1; i <= n; i++) {
for(int j = half; j >= 0; j--) {
if(j >= w[i]) {
f[j] = max(f[j], f[j-w[i]] + w[i]);
}
}
}
return f[half];
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
w[i] /= 1024;
W += w[i];
}
int res = DP();
cout << max(res, W-res)*1024 << endl;
return 0;
}
调整队列
在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n - 1)。其中有一些是男生,有一些是女生,男生用’B’表示,女生用’G’表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:GGBBG->GGBGB->GGGBB
这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次
输入描述 :
输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.
输出描述 :
输出一个整数,表示最少需要的调整队伍的次数
输入例子 :
GGBBG
输出例子 :
2
思考:这道题最终只有两种结果,最直观的想法是模拟这个调整的过程。
其实可以直接通过下标计算求得结果,参考代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int work(string s, char ch);
string str;
int main()
{
cin >> str;
int n = work(str, 'G');
int m = work(str, 'B');
cout << min(n, m) << endl;
return 0;
}
int work(string s, char ch) {
int indexSum = 0;
int num = 0;
for(int i = 0; i < (int)s.length(); i++) {
if(s[i] == ch) {
num++;
indexSum += i;
}
}
int res = indexSum - (num*(num-1))/2;
return res;
}
凃棋盘
小易有一块n*n的棋盘,棋盘的每一个格子都为黑色或者白色,小易现在要用他喜欢的红色去涂画棋盘。
小易会找出棋盘中某一列中拥有相同颜色的最大的区域去涂画,帮助小易算算他会涂画多少个棋格。
输入描述 :
输入数据包括n + 1行:
第一行为一个整数n(1 ≤ n ≤ 50), 即棋盘的大小
接下来的n行每行一个字符串表示第i行棋盘的颜色,’W’表示白色,’B’表示黑色
输出描述 :
输出小易会涂画的区域大小
输入例子 :
3
BWW
BBB
BWB
输出例子 :
3
思路:B转为0, W转为1。然后每一列为一个数组单独处理。
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 55;
int mat[maxn][maxn];
///B for 0 W for 1
int n;
int work(vector<int> &v) {
int num[maxn];
num[0] = 1;
for(unsigned i = 1; i < v.size(); i++) {
if(v[i] == v[i-1]) {
num[i] = num[i-1] + 1;
} else {
num[i] = 1;
}
}
int maxValue = -1;
for(int i = 0; i < n; i++) {
maxValue = max(maxValue, num[i]);
}
return maxValue;
}
int main()
{
cin >> n;
string str;
for(int i = 0; i < n; i++) {
cin >> str;
for(int j = 0; j < (int)str.length(); j++) {
if(str[j] == 'B') {
mat[i][j] = 0;
} else {
mat[i][j] = 1;
}
}
}
int maxValue = -1;
vector<int> V;
for(int j = 0; j < n; j++) {
for(int i = 0; i < n; i++) {
V.push_back(mat[i][j]);
}
int res = work(V);
maxValue = max(maxValue, res);
V.clear();
}
cout << maxValue << endl;
return 0;
}
/**
测试数据:
3
BWW
BBB
BWB
3
8
BBWWBBWW
BBWWBBWW
WWBBWWBB
WWBBWWBB
BBWWBBWW
BBWWBBWW
WWBBWWBB
WWBBWWBB
2
**/
消除重复元素
小易有一个长度为n序列,小易想移除掉里面的重复元素,但是小易想是对于每种元素保留最后出现的那个。小易遇到了困难, 希望你来帮助他。
输入描述 :
输入包括两行:
第一行为序列长度n(1 ≤ n ≤ 50)
第二行为n个数sequence[i](1 ≤ sequence[i] ≤ 1000),以空格分隔
输出描述 :
输出消除重复元素之后的序列,以空格分隔,行末无空格
输入例子 :
9
100 100 100 99 99 99 100 100 100
输出例子 :
99 100
思路:用set判断重复, 用stack保持其有序性。
#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <stack>
using namespace std;
int main()
{
int n;
int read;
cin >> n;
set<int> mySet;
vector<int> V;
stack<int> resultStack;
for(int i = 0; i < n; i++) {
cin >> read;
V.push_back(read);
}
int len = V.size();
set<int>::iterator it;
for(int i = len-1; i >= 0; i--) {
it = mySet.find(V[i]);
if(it != mySet.end()) {
continue;
} else {
mySet.insert(V[i]);
resultStack.push(V[i]);
}
}
int top = resultStack.top();
cout << top;
resultStack.pop();
while(!resultStack.empty()) {
cout << " " << resultStack.top() ;
resultStack.pop();
}
return 0;
}
工作安排
现在有n位工程师和6项工作(编号为0至5),现在给出每个人能够胜任的工作序号表(用一个字符串表示,
比如:045,表示某位工程师能够胜任0号,4号,5号工作)。现在需要进行工作安排,
每位工程师只能被安排到自己能够胜任的工作当中去,两位工程师不能安排到同一项工作当中去。
如果两种工作安排中有一个人被安排在的工作序号不一样就被视为不同的工作安排,现在需要计算出有多少种不同工作安排计划。
输入描述:
输入数据有n+1行:
第一行为工程师人数n(1 ≤ n ≤ 6)
接下来的n行,每行一个字符串表示第i(1 ≤ i ≤ n)个人能够胜任的工作(字符串不一定等长的)
输出描述:
输出一个整数,表示有多少种不同的工作安排方案
输入例子:
6
012345
012345
012345
012345
012345
012345
输出例子:
720
思考:此题数据量不大,代码用的dfs,可以思考如果增大数据量该怎么做。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
void dfs(int index);
const int maxn = 10;
vector<string> v;
int n;
bool vis[maxn]; //记录是否分配过
int totalMethod = 0;
int main()
{
cin >> n;
getchar();
string str;
for(int i = 0; i < n; i++) {
getline(cin, str);
v.push_back(str);
}
memset(vis, false, sizeof(vis));
dfs(0);
cout << totalMethod << endl;
return 0;
}
//index 代表是下标为index的人
void dfs(int index) {
string str = v[index];
for(unsigned i = 0; i < str.length(); i++) {
int id = str[i]-'0';
if(!vis[id]) {
if(index == n-1) {
totalMethod++;
continue;
} else {
vis[id] = true;
dfs(index+1);
vis[id] = false;
}
}
}
}
小易记单词
小易参与了一个记单词的小游戏。游戏开始系统提供了m个不同的单词,小易记忆一段时间之后需要在纸上写出他记住的单词。小易一共写出了n个他能记住的单词,如果小易写出的单词是在系统提供的,将获得这个单词长度的平方的分数。
注意小易写出的单词可能重复,但是对于每个正确的单词只能计分一次。
输入描述 :
输入数据包括三行:
第一行为两个整数n(1 ≤ n ≤ 50)和m(1 ≤ m ≤ 50)。以空格分隔
第二行为n个字符串,表示小易能记住的单词,以空格分隔,每个单词的长度小于等于50。
第三行为m个字符串,系统提供的单词,以空格分隔,每个单词的长度小于等于50。
输出描述 :
输出一个整数表示小易能获得的分数
输入例子 :
3 4
apple orange strawberry
strawberry orange grapefruit watermelon
输出例子 :
136
#include <iostream>
#include <cstdio>
#include <string>
#include <set>
using namespace std;
const int maxn = 55;
set<string> mem;
set<string> provide;
int n, m;
int main() {
cin >> n >> m;
char read[maxn];
for(int i = 0; i < n; i++) {
scanf("%s", read);
string str = string(read);
mem.insert(str);
}
for(int i = 0; i < m; i++) {
scanf("%s", read);
string str = string(read);
provide.insert(str);
}
set<string>::iterator it;
set<string>::iterator pit;
int score = 0;
for(it = mem.begin(); it != mem.end(); it++) {
pit = provide.find(*it);
if(pit != provide.end()) {
string s = *it;
score += s.length() * s.length();
}
}
cout << score << endl;
return 0;
}
奇怪的表达式求值
常规的表达式求值,我们都会根据计算的优先级来计算。比如, / 的优先级就高于 + -。但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没有除法,意味着表达式中没有 / ,只有(+, -和 )。现在给出一个表达式,需要你帮忙计算出小易所在的世界这个表达式的值为多少
输入描述 :
输入为一行字符串,即一个表达式。其中运算符只有 - , +, *。参与计算的数字只有0~9.
保证表达式都是合法的,排列规则如样例所示。
输出描述 :
输出一个数,即表达式的值
输入例子 :
3 + 5 * 7
输出例子 :
56
思路:题目不难,首先我是把操作数和运算符分开
操作数用dequeue维护可以在前端插入。
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <deque>
using namespace std;
deque<int> num;
queue<char> operate;
//把数字和运算符分开
void separate(string &str) {
for(int i = 0; i < (int)str.length(); i++) {
if(str[i]>= '0' && str[i] <= '9') {
num.push_back(str[i]-'0');
} else {
operate.push(str[i]);
}
}
}
int calculate() {
while(!num.empty()) {
if(num.size() == 1) break;
int x = num.front();
num.pop_front();
int y = num.front();
num.pop_front();
char ch = operate.front();
operate.pop();
int z = 0;
switch(ch) {
case '+':
z = x + y;
break;
case '-':
z = x - y;
break;
case '*':
z = x * y;
break;
}
num.push_front(z);
}
int res = num.front();
return res;
}
int main()
{
string str;
getline(cin, str);
separate(str);
int res = calculate();
cout << res << endl;
return 0;
}
/**
7*9-2*0+2
输入例子 :
3 + 5 * 7
输出例子 :
56
**/
另外一篇博客:http://blog.csdn.net/cqk0100/article/details/73010307