CH2401
题目:作为惩罚,GY被遣送去帮助某神牛给女生送礼物(GY:貌似是个好差事)但是在GY看到礼物之后,他就不这么认为了。某神牛有N个礼物,且异常沉重,但是GY的力气也异常的大(-_-b),他一次可以搬动重量和在w(w<=2^31-1)以下的任意多个物品。GY希望一次搬掉尽量重的一些物品,请你告诉他在他的力气范围内一次性能搬动的最大重量是多少。
本题直接dfs也可以写,但是看到数据规模(对于100%的数据 N<=45 W<=2^31-1),直接dfs肯定要超时的;所以用到双向搜索
如图就是dfs(左),和双向搜索(右)的区别(好丑)
那么可以将数据分成两半,前一半朴素dfs,存储运行结果,后一半匹配前一半结果进行搜索
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
long long w,n;
long long now=0;
long long a[100],b[1<<23+1];
long long m;
long long ans=0;
bool cmp(int a,int b){
return a>b;
}
void dfs1(int s,int e){
if(now>w){//加多了
return ;
}
if(s>e){//若遍历完
m++;
b[m]=now;
// cout<<now<<" ";
return ;
}
dfs1(s+1,e);//不拿这个
now+=a[s];
dfs1(s+1,e);//拿
now-=a[s];
}
void dfs2(int s,int e){
if(now>w){//加多了
return ;
}
if(s>e){//若遍历完
if(b[1]+now > w) return ;//如果现在的值加上前半最小的都比w大就没有再二分的必要
long long c=w-now;
ans=max((b[upper_bound(b+1,b+1+m,c)-b-1]+now),ans);
return ;
}
dfs2(s+1,e);//不拿这个
now+=a[s];
dfs2(s+1,e);//拿
now-=a[s];
}
int main(){
cin>>w>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n,cmp);
dfs1(1,n/2);
/*
b数组存储了所有前一半可以加出来的可行情况
for(int i=1;i<=m;i++){
cout<<b[i]<<" ";
} */
sort(b+1,b+m+1);
dfs2(n/2+1,n);
cout<<ans;
return 0;
}
/*
20 5
7
5
4
18
1
*/
CH2501
思路:以每个1为起点,分别进行深搜
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int n,m;
char a[3000][3000];
int s[3000][3000],l[3000][3000];
int m1[4]={-1,1,0,0};
int m2[5]={0,0-1,1};
queue<pair<int,int> > q;
int main(){
memset(l,-1,sizeof(l));
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",a[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]='1'){
l[i][j]=0;
q.push(make_pair(i,j));
}
}
}
while(q.size()){
pair<int,int> now=q.front();
q.pop();
for(int i=0;i<4;i++){
pair<int,int> next=make_pair((now.first+m1[i]),(now.second +m2[i]));
if(next.first <1||next.second <1||next.first >n||next.second >m) {
continue;
}
if(l[next.first][next.second]==-1){
l[next.first][next.second]=l[now.first ][now.second ]+1;
q.push(next);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<l[i]<<" ";
}
cout<<endl;
}
return 0;
}