您的位置:首页 > 编程语言 > C语言/C++

算法-蓝桥杯-算法训练 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
  
  可以看到,最后y值变成了1,也就完成了我们的任务。输入格式  第一行你会得到用空格分开的两个整数N(1<=N<=100)和W(-10^9<=W<=10^9),(N为需要算加法的数字个数,W是你希望算出的数)。
  第二行你会得到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 结束语

    问题的讲解可以参考这篇博客。点击打开链接
    分享和帮助是人生一大乐事,希望可以帮助您。本人才疏学浅,如果有不当之处,还请批评指正。同时欢迎大家评论、点赞及转发!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息