算法-蓝桥杯-算法训练 Multithreading (C++)
2018-03-26 17:20
375 查看
1 引言
一道难题。。。2 题目
问题描述 现有如下一个算法:repeat ni times
yi := y
y := yi+1
end repeat
令n[1]为你需要算加法的第一个数字,n[2]为第二个,...n
为第N个数字(N为需要算加法的数字个数),
并令y初始值为0,先令i=1运行这个算法(如上所示,重复n[i]次),然后令i=2运行这个算法。。直到i=N。注意y值一直不要清零。最后y的值就是你需要的加法答案。
你想知道,有没有某种运算顺序能使答案等于W。
一个循环中的全部语句,是不能改变在总的语句排列中的相对顺序的。
(这里的第i个循环是指这n[i]*2条语句。就是你把属于第i个循环的语句抽出来看,它们需要按照原顺序排列。在你没有运行完这个循环的最靠前一条未完成的 语句的时候,你是不能跳过它先去完成这个循环后面的语句的。你能做的仅是把若干个循环按照你所规定的顺序“归并”起来。)
举个例子,n[1]= 2 ,n[2]=1, W=1.一种可行的运算顺序是“2 1 1 1 1 2”,数字为几表示运行第几个算法的下一条语句(你可以看到”1”出现了4次,是因为n[1]=2即循环两次,而每次循环里面有两条语句,所以2*2=4次)
y值 | y[1] 值 | y[2] 值 | |
执行0条语句过后 | 0 | 0 | 0 |
执行1条过后(y[2]=y) | 0 | 0 | 0 |
执行2条过后(y[1]=y) | 0 | 0 | 0 |
执行3条过后(y=y[1]+1) | 1 | 0 | 0 |
执行4条过后(y[1]=y) | 1 | 1 | 0 |
执行5条过后(y=y[1]+1) | 2 | 1 | 0 |
执行6条过后(y=y[2]+1) | 1 | 1 | 0 |
第二行你会得到n个整数n[i] (1<=n[i]<=1000).输出格式 第一行您应该输出Yes(若能以某种顺序使得这个算法得出W的值) 或No。
如果第一行是No,接下来就不用继续输出了。
如果是Yes, 请在第2行输出2*sigma(n[i])个用空格隔开的数,表示任意一种满足条件的运算顺序。样例输入1 10
11样例输出No样例输入2 3
4 4样例输出Yes
1 1 2 1 2 2 2 2 2 1 2 1 1 1 1 2样例输入3 6
1 2 3样例输出Yes
1 1 2 2 2 2 3 3 3 3 3 3数据规模和约定 对于30%的数据,n<=4, n[i]的和小于10.
对于100%的数据,n<=100 , -10^9<=W<=10^9, 1<=n[i]<=1000
3 源代码
#include<iostream>#include<cstdlib>
using namespace std;
struct Num{
int pos;
int value;
};
//比较函数
int comp(const void* pa,const void* pb){
Num* a=(Num*)pa;
Num* b=(Num*)pb;
if(a->value!=b->value){
return a->value-b->value;
}else{
return a->pos-b->pos;
}
}
const int maxLen=101;
int main(){
//输入数组长度,期待值,数组的值
int len,w;
cin>>len>>w;
Num nums[maxLen];
for(int index=1;index<=len;index++){
cin>>nums[index].value;
nums[index].pos=index;
}
if(w==1){
int numIndex=1;
for(;numIndex<=len;numIndex++){
if(nums[numIndex].value==1){
cout<<"Yes"<<endl;
//用值为1的数组消除其他数组
cout<<nums[numIndex].pos<<' ';
for(int index=1;index<=len;index++){
if(index!=numIndex){
for(int j=0;j<nums[index].value;j++){
cout<<nums[index].pos<<' '<<nums[index].pos<<' ';
}
}
}
cout<<nums[numIndex].pos<<' ';
return 0;
}
}
cout<<"No"<<endl;
return 0;
}
//如果只输入一个数,只有该数等于期待值才能满足条件
if(len==1){
if(nums[1].value==w){
cout<<"Yes"<<endl;
for(int index=0;index<nums[1].value;index++){
cout<<nums[1].pos<<' '<<nums[1].pos<<' ';
}
}else{
cout<<"No"<<endl;
}
}else{
//从小到大排序
qsort((void*)(nums+1),len,sizeof(Num),(int(*)(const void*,const void*))comp);
//数组索引从1开始,计算数组的和
int sum=0;
int numIndex=1;
//如果总数大于等于期待值就跳出
for(;numIndex<=len;numIndex++){
sum+=nums[numIndex].value;
if(sum>=w){
break;
}
}
//如果总数小于期待值肯定不能的
if(sum<w){
cout<<"No"<<endl;
}else if(sum==w){ //如果前面数的和刚好等于期待值
cout<<"Yes"<<endl;
cout<<nums[1].pos<<' ';
for(int j=numIndex+1;j<=len;j++){
for(int k=0;k<nums[j].value;k++){
cout<<nums[j].pos<<' ' <<nums[j].pos<<' ';
}
}
cout<<nums[1].pos<<' ';
//因为执行过一次
nums[1].value--;
for(int j=1;j<=numIndex;j++){
for(int k=0;k<nums[j].value;k++){
cout<<nums[j].pos<<' '<<nums[j].pos<<' ';
}
}
}else{
//第一个数就大于w,或几个数加起来才大于w
cout<<"Yes"<<endl;
if(numIndex==1){
cout<<nums[2].pos<<' ';
//只保留第一数组的1个
for(int index=0;index<nums[1].value-1;index++){
cout<<nums[1].pos<<' '<<nums[1].pos<<' ';
}
//3以后的数字都消除
for(int index=3;index<=len;index++){
for(int j=0;j<nums[index].value;j++){
cout<<nums[index].pos<<' '<<nums[index].pos<<' ';
}
}
cout<<nums[2].pos<<' ';
//因为执行过一次
nums[2].value--;
//把2执行到 y=w-1
for(int index=0;index<w-2;index++){
cout<<nums[2].pos<<' '<<nums[2].pos<<' ';
nums[2].value--;
}
cout<<nums[1].pos<<' ';
for(int index=0;index<nums[2].value;index++){
cout<<nums[2].pos<<' '<<nums[2].pos<<' ';
}
cout<<nums[1].pos<<' ';
}else{
int t=sum-w;
cout<<nums[1].pos<<' ';
//消除当前数组多出的循环
for(int index=0;index<t;index++){
cout<<nums[numIndex].pos<<' '<<nums[numIndex].pos<<' ';
nums[numIndex].value--;
}
//消除当前数组之后的循环
for(int index=numIndex+1;index<=len;index++){
for(int j=0;j<nums[index].value;j++){
cout<<nums[index].pos<<' '<<nums[index].pos<<' ';
}
}
cout<<nums[1].pos<<' ';
//因为执行过一次
nums[1].value--;
//把之前的都输出
for(int index=0;index<=numIndex;index++){
for(int j=0;j<nums[index].value;j++){
cout<<nums[index].pos<<' '<<nums[index].pos<<' ';
}
}
}
}
}
return 0;
}
5 结束语
问题的讲解可以参考这篇博客。点击打开链接分享和帮助是人生一大乐事,希望可以帮助您。本人才疏学浅,如果有不当之处,还请批评指正。同时欢迎大家评论、点赞及转发!
相关文章推荐
- 算法-蓝桥杯-算法训练 Beaver's Calculator (C++)
- 算法训练 比较字符串 (蓝桥杯C++)
- 算法-蓝桥杯-算法训练 逆序对(C++)
- 算法-蓝桥杯-算法训练 C++ CH08 01 (C++)
- 蓝桥杯 算法训练 Multithreading (全面解释)
- 算法-蓝桥杯-算法训练 操作格子(C++)
- 算法-蓝桥杯-算法训练 Cowboys(C++)
- 算法-蓝桥杯-算法训练 Lift and Throw (C++)
- 算法-蓝桥杯-算法训练 安慰奶牛(C++)
- 蓝桥杯算法训练 6-1 递归求二项式系数值
- 算法-蓝桥杯-算法训练 前缀表达式 (JAVA)
- 算法-蓝桥杯-算法训练 2的次幂表示 (JAVA)
- 蓝桥杯 算法训练 明明的随机数
- 蓝桥杯 算法训练VIP s01串(Java解题)
- 蓝桥杯 算法训练VIP 阶乘(Java解题)
- 蓝桥杯算法训练——字符统计
- 2013年第四届蓝桥杯C/C++B组真题训练(一,2017.3.3)
- 蓝桥杯 算法训练 乘积最大 dp
- 蓝桥杯算法训练回文数
- 蓝桥杯算法训练 校门外的树