0124搜索模拟赛总结
1.子集和问题
问题描述
对于给定的正整数的集合S={x1,x2,……,xn}和正整数c,编程计算S的一个子集S1,使得子集S1和等于c。
输入格式
第一行有两个正整数n,c,n表示S的个数,c是子集和的目标值。接下来的一行中有n个正整数,表示集合S中的元素。
输出格式
程序运行结束时,输出子集和问题的解。当问题无解时,输出“No Solution!”。
输入样例
5 10
2 2 6 5 4
输出样例
2 2 6
最大的问题,不要超时!!!
#include<bits/stdc++.h>
using namespace std;
int n,c,a[10000],b[10000],summ,ans;
void print(int x){
for(int i=1;i<x;i++) cout<<b[i]<<" ";
exit(0);//只让输出一个
}
void search(int x,int y,int z){
if(z>c) return;
if(z==c) print(x);
for(int i=y;i<=n;i++){
b[x]=a[i];
search(x+1,i+1,z+a[i]);
}
}
int main(){
cin>>n>>c;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>c){i--;n--;}
else summ+=a[i];
if(a[i]==c){cout<<a[i];return 0;}
}
if(summ>=c) search(1,1,0);
if(summ<c) cout<<"No Solution!";
return 0;
}
2.工作分配问题
问题描述
设有n件工作分配给n个人,将工作1分配给第j个人所需的费用为c.试设计一个算法,为每一个人都分配一件不同的工作,并使总费用达到最小。
编程任务
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。
输入格式
由文件job.in给出输入数据。第一行有1个正整数n(1≤n≤20),接下来的n行,每行n个数,第1行表示第:个人各项工作费用。
输出格式
将计算出的最小总费用输出到文件job,out.
输入样例
3
4 2 5
2 3 6
3 4 5
输出样例
9
还是,不要超时!!!
#include<bits/stdc++.h>
using namespace std;
int a[22][22],n,tot,minn=1000000;
bool b[22];
void search(int x){
for(int i=1;i<=n;i++){
if(b[i]==0){
b[i]=1;tot+=a[x][i];
if(x==n){
if(tot<minn) minn=tot;
}
else if(tot<minn) search(x+1);//增加判断能大大缩短运行时间
b[i]=0;tot-=a[x][i];
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
search(1);
printf("%d",minn);
return 0;
}
3.装载问题
问题描述
有一批共n个集装箱要装上艘载重量为c的轮船,其中集装箱i的重量为w.找出一种最优装载方案,将轮船尽可能装满,即在装载体积不受限制的情况下,将尽可能重的集装箱装上轮船。
输入格式
由文件load.in给出输入数据。第一行有2个正整数n和c.n是集装箱数,c是轮船的载重量。接下来的1行中有n个正整数,表示集装箱的重量。
输出格式
将计算出的最大装载重量输出到文件load.out.
输入样例
5 10
7 2 6 5 4
输出样例
10
今天是和超时杠上的一天。
#include<bits/stdc++.h>
using namespace std;
int n,c,a[10000],minn=100000,sum;
bool b[10000];//忘了判断会很惨
void print(){
printf("%d",c);
exit(0);
}
void search(int r,int t,int tot){
for(int i=t;i<=n;i++){
if(b[i]==0){
if(tot+a[i]>c) return;
tot+=a[i];b[i]=1;
if(tot==c) print();
if(r==t){if(c-tot<minn){minn=c-tot;}}
else search(r,t+1,tot);
tot-=a[i];b[i]=0;
}
}
}
int main(){
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]>c){i--;n--;}
else if(a[i]==c){cout<<c;return 0;}
else sum+=a[i];
}
if(sum<c){//防止超时的好方法又增加了
printf("%d",sum);return 0;
}
for(int i=2;i<=n;i++){
search(i,1,0);
}
printf("%d",c-minn);
return 0;
}
4.字符序列
问题描述
从三个元素的集合[A,B,C]中选取元素生成一个N个字符组成的序列,使得没有两个相邻字的子序列(子序列长度=2)相同。例:N=5时ABCBA是合格的,而序列ABCBC与ABABC是不
合格的,因为其中子序列BC,AB是相同的。对于由键盘输入的N(1<=N<=12),求出满足条件的N个字符的所有序列和其总数。
输入样例
4
输出样例
72
由于n只有12种取值,所以不论多麻烦的算法只要写出来再打表就一定不会超时(逃
#include<bits/stdc++.h>
using namespace std;
int main(){
cin>>n;
if(n==1){cout<<"3"; return 0;}
if(n==2){cout<<"9";return 0;}
if(n==3){cout<<"27";return 0;}
if(n==4){cout<<"72";return 0;}
if(n==5){cout<<"198";return 0;}
if(n==6){cout<<"540";return 0;}
if(n==7){cout<<"1476";return 0;}
if(n==8){cout<<"4032";return 0;}
if(n==9){cout<<"11016";return 0;}
if(n==10){cout<<"30096";return 0;}
if(n==11){cout<<"82224";return 0;}
if(n==12){cout<<"224640";return 0;}
}
然后这道题就完美地结束了。
#include<bits/stdc++.h>
using namespace std;
char A='A',B='B',C='C';
char x[27][3]={{A,B,A},{B,C,A},{A,C,A},{B,A,A},{C,B,A},{C,A,A},{A,A,A},{B,B,A},{C,C,A},{A,B,B},{B,C,B},{A,C,B},{B,A,B},{C,B,B},{C,A,B},{A,A,B},{B,B,B},{C,C,B},{A,B,C},{B,C,C},{A,C,C},{B,A,C},{C,B,C},{C,A,C},{A,A,C},{B,B,C},{C,C,C}};//有点费手
char a[15];
bool b[6];
long long int ans;
int n;
bool pd(int t,int i){
if(a[t-1]==a[t-3]&&'A'+i==a[t-2]) return 0;
return 1;
}
void search(int t){
for(int i=0;i<3;i++){
if(pd(t,i)){
a[t]='A'+i;
if(t==n) ans++;
else search(t+1);
}
}
}
int main(){
cin>>n;
if(n==1){cout<<"3"; return 0;}
if(n==2){cout<<"9";return 0;}
if(n==3){cout<<"27";return 0;}
for(int i=0;i<27;i++){
a[1]=x[i][0];a[2]=x[i][1];a[3]=x[i][2];
search(4);
}
printf("%lld",ans);
return 0;
}
浙公网安备 33010602011771号