一、普通

cpp
#include<bits/stdc++.h>
using namespace std;
int n,c[20],ans=1e9,car[20],cnt,w;
void dfs(int x){
if(x==n+1){
ans=min(ans,cnt);
return ;
}
if(ans<=cnt)return ;
car[++cnt]=c[x];dfs(x+1);
cnt--;
for(int i=1;i<=cnt;i++){
if(car[i]+c[x]<=w){
car[i]+=c[x];
dfs(x+1);
car[i]-=c[x];
}
}
}
int main(){
scanf("%d%d",&n,&w);
for(int i=1;i<=n;i++){
scanf("%d",&c[i]);
}
sort(c+1,c+n+1,greater<int>());
dfs(1);
printf("%d",ans);
return 0;
}

cpp
#include<bits/stdc++.h>
using namespace std;
int r[10],c[10],g[10],mp[10][10],fd;
char s[90];
inline int P(int i,int j){
return (i/3)*3+(j/3);
}
void dfs(){
if(fd==1)return;
int f=1;int x=0,y=0,p=0,l=0,o;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(mp[i][j]==-1){
f=0;
o=r[i]|c[j]|g[P(i,j)];
if(o==(1<<9)-1){
return;
}
else{
if(__builtin_popcount(o)>p){
p=__builtin_popcount(o);
l=(o);
x=i,y=j;
}
}
}
}
}
if(f){
fd=1;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
printf("%d",mp[i][j]+1);
}
}
printf("\n");
return;
}
int u=r[x],v=c[y],w=g[P(x,y)];
for(register int i=0;i<9;i++){
if(!((l>>i)&1)){
r[x]|=(1<<i);
c[y]|=(1<<i);
g[P(x,y)]|=(1<<i);
mp[x][y]=i;
dfs();
mp[x][y]=-1;
r[x]=u;
c[y]=v;
g[P(x,y)]=w;
}
}
}
int main(){
while(scanf("%s",s)){
fd=0;
if(s[0]=='e')break;
for(int i=0;i<9;i++){
r[i]=c[i]=g[i]=0;
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(s[i*9+j]=='.'){mp[i][j]=-1;}
else{
mp[i][j]=s[i*9+j]-'1';
r[i]|=(1<<mp[i][j]);
c[j]|=(1<<mp[i][j]);
g[P(i,j)]|=(1<<mp[i][j]);
}
}
}
dfs();
}
return 0;
}

cpp
#include<bits/stdc++.h>
using namespace std;
int n,a[70],sum,len,cnt,v[70];
int dfs(int x,int l,int la){
if(l==len){
return dfs(x+1,0,1);
}
if(x==cnt+1){
return 1;
}
int lf=-1,res;
for(int i=la;i<=n;i++){
if(v[i]==0&&a[i]!=lf&&a[i]+l<=len){
v[i]=1;
res=dfs(x,l+a[i],i+1);
v[i]=0;
if(res){
return 1;
}
lf=a[i];
if(l==0||l+a[i]==len)return 0;
}
}
return 0;
}
int main(){
while(~scanf("%d",&n)&&n){
sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a+1,a+n+1,greater<int>());
for(len=1;len<=sum;len++){
if(sum%len)continue;
cnt=sum/len;
if(dfs(1,0,1)){
printf("%d\n",len);
break;
}
}
}
return 0;
}


cpp
#include<bits/stdc++.h>
using namespace std;
int n,m,r[25],h[25],ans=1e9,ms[25],mv[25];
void dfs(int dep,int v,int s){
if(dep==0){
if(v==n)ans=min(ans,s);
return ;
}
if(s+ms[dep-1]>ans||v+mv[dep-1]>n||s+2*(n-v)/r[dep+1]>ans)return ;
for(int R=min(r[dep+1]-1,(int)sqrt(n-v));R>=dep ;R--){
for(int H=min(h[dep+1]-1,(n-v)/R/R);H>=dep;H--){
h[dep]=H;r[dep]=R;
if(dep==m)dfs(dep-1,v+R*R*H,s+2*R*H+R*R);
else dfs(dep-1,v+R*R*H,s+2*R*H);
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=20;i++){
ms[i]=ms[i-1]+2*i*i;
mv[i]=mv[i-1]+i*i*i;
}
h[m+1]=1e9;r[m+1]=1e9;
dfs(m,0,0);
if(ans!=1e9)printf("%d",ans);
else printf("0");
return 0;
}

cpp
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
string S[20];
int fd=0;
int mp[17][17],id[17][17],s[17][17];
int r[17],c[17],g[17],jl[30000][17][17],tot,lr[30000][17],lc[30000][17],lg[30000][17],lmp[30000][17][17];
pair<int,int>ad[17]={{0,0},{0,4},{0,8},{0,12},
{4,0},{4,4},{4,8},{4,12},
{8,0},{8,4},{8,8},{8,12},
{12,0},{12,4},{12,8},{12,12}};
unordered_map<int,int>p;
inline bool jq(int a,int b){
return (a>>b)&1;
}
inline int lowbit(int x){
return x&(-x);
}
inline void draw(int i,int j,int x){
mp[i][j]=x;
r[i]|=(1<<x);
c[j]|=(1<<x);
g[id[i][j]]|=(1<<x);
for(register int d=0;d<16;d++){
s[i][d]|=(1<<x);
s[d][j]|=(1<<x);
}
for(register int u=ad[id[i][j]].first;u<ad[id[i][j]].first+4;u++)
for(register int v=ad[id[i][j]].second;v<ad[id[i][j]].second+4;v++)
s[u][v]|=(1<<x);
}
inline void re(int now){
for(register int i=0;i<16;i++)r[i]=lr[now][i],c[i]=lc[now][i],g[i]=lg[now][i];
for(register int i=0;i<16;i++)for(register int j=0;j<16;j++)s[i][j]=jl[now][i][j],mp[i][j]=lmp[now][i][j];
}
inline void init(){
for(register int i=0;i<16;i++){
for(register int j=0;j<16;j++){
s[i][j]=(r[i]|c[j]|g[id[i][j]]);
}
}
}
void print(){
for(register int i=0;i<16;i++){
for(register int j=0;j<16;j++){
if(mp[i][j]==-1)printf("-");
else printf("%c",mp[i][j]+'A');
}
printf("\n");
}
printf("\n");
}
void prints(){
for(int i=0;i<16;i++){
for(int j=0;j<16;j++){
printf("%d ",s[i][j]);
}
printf("\n");
}
printf("\n");
}
void printr(){
for(int i=0;i<16;i++){
printf("%d ",r[i]);
}
puts("");
}
void dfs(){
//cout<<tot<<endl;
if(fd)return;
{//jz1
for(register int i=0;i<16;i++)for(register int j=0;j<16;j++)if(mp[i][j]==-1){
if(s[i][j]==(1<<16)-1){
return;
}
if(__builtin_popcount(s[i][j])==15){
draw(i,j,p[lowbit(~s[i][j])]);
dfs();return ;
}
}
}
{//z2
int x,y,f=2;
for(register int i=0;i<16;i++){
for(register int ch=0;ch<16;ch++){
if(jq(r[i],ch))continue;
f=0;
for(int j=0;j<16;j++){
if(mp[i][j]!=-1)continue;;
if(!jq(s[i][j],ch)){
f++;
x=i,y=j;
}
}
if(f==0){
return;
}
if(f==1){
draw(x,y,ch);dfs();
return ;
}
}
}
}
{//zj3
int x,y,f=2;
for(register int j=0;j<16;j++){
for(register int ch=0;ch<16;ch++){
if(jq(c[j],ch))continue;
f=0;
for(int i=0;i<16;i++){
if(mp[i][j]!=-1)continue;;
if(!jq(s[i][j],ch)){
f++;
x=i,y=j;
}
}
if(f==0){
return;
}
if(f==1){
draw(x,y,ch);dfs();return;
}
}
}
}
{//zj4
int x,y,f=2;
for(register int k=0;k<16;k++){
for(register int ch=0;ch<16;ch++){
if(jq(g[k],ch))continue;
f=0;
for(int i=ad[k].first;i<ad[k].first+4;i++){
for(int j=ad[k].second;j<ad[k].second+4;j++){
if(mp[i][j]!=-1)continue;;
if(!jq(s[i][j],ch)){
f++;
x=i,y=j;
}
}
}
if(f==0)return;
if(f==1){
draw(x,y,ch);dfs();
return ;
}
}
}
}
{//bj
int flag=1;
for(register int i=0;i<16;i++){
for(register int j=0;j<16;j++){
if(mp[i][j]==-1){
flag=0;
}
}
}
if(flag){
fd=1;
print();
return ;
}
}
{//zy
int x,y,ma=0,now=++tot;
for(register int i=0;i<16;i++)for(register int j=0;j<16;j++)jl[now][i][j]=s[i][j],lmp[now][i][j]=mp[i][j];
for(register int i=0;i<16;i++)lr[now][i]=r[i],lc[now][i]=c[i],lg[now][i]=g[i];
for(register int i=0;i<16;i++)for(register int j=0;j<16;j++)if(mp[i][j]==-1){
if(__builtin_popcount(s[i][j])>ma){
ma=__builtin_popcount(s[i][j]);
x=i,y=j;
}
}
for(register int ch=0;ch<16;ch++){
if(!jq(s[x][y],ch)){
draw(x,y,ch);
dfs();
re(now);
}
}
}
}
int main(){
for(int i=0;i<=16;i++){
p[1<<i]=i;
}
while(cin>>S[0]){
tot=0;
memset(r,0,sizeof(r));
memset(c,0,sizeof(c));
memset(g,0,sizeof(g));
memset(mp,0,sizeof(mp));
memset(s,0,sizeof(s));
fd=0;
for(int i=1;i<16;i++){
cin>>S[i];
}
for(int i=0;i<16;i++){
for(int j=0;j<16;j++){
id[i][j]=(i/4)*4+j/4;
if(S[i][j]=='-')mp[i][j]=-1;
else mp[i][j]=S[i][j]-'A',r[i]|=(1<<mp[i][j]),c[j]|=(1<<mp[i][j]),g[id[i][j]]|=(1<<mp[i][j]);
}
}
init();
dfs();
//printf("%d",fd);
}
return 0;
}
同9*9数独,剪枝是
cpp
#include<bits/stdc++.h>
using namespace std;
#define pr for(int i=0;i<9;i++){for(int j=0;j<9;j++)printf("%d ",mp[i][j]+1);puts("");}puts("");
int mp[9][9],ans,id[9][9],r[9],c[9],g[9],cs;
int sc[9][9]={{6,6,6,6,6,6,6,6,6},{6,7,7,7,7,7,7,7,6},{6,7,8,8,8,8,8,7,6},{6,7,8,9,9,9,8,7,6},{6,7,8,9,10,9,8,7,6},{6,7,8,9,9,9,8,7,6},{6,7,8,8,8,8,8,7,6},{6,7,7,7,7,7,7,7,6},{6,6,6,6,6,6,6,6,6},};
void dfs(int v){
int f=81,o,ma=0,x,y,s;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(mp[i][j]!=-1)continue;
f--;
o=(r[i]|c[j]|g[id[i][j]]);
if(o==(1<<9)-1)return;
if(__builtin_popcount(o)>=ma){
x=i,y=j;
ma=__builtin_popcount(o);
s=o;
}
}
}
if(f==81){
ans=max(ans,v);return;
}
for(int ch=8;ch>=0;ch--){
if(!((s>>ch)&1)){
mp[x][y]=ch;
r[x]|=(1<<ch);
c[y]|=(1<<ch);
g[id[x][y]]|=(1<<ch);
dfs(v+sc[x][y]*(ch+1));
mp[x][y]=-1;
r[x]&=(~(1<<ch));
c[y]&=(~(1<<ch));
g[id[x][y]]&=(~(1<<ch));
}
}
}
int main(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
scanf("%d",&mp[i][j]);
mp[i][j]--;id[i][j]=i/3*3+j/3;
if(mp[i][j]!=-1){
cs+=mp[i][j]*sc[i][j]+sc[i][j];
r[i]|=(1<<mp[i][j]);
c[j]|=(1<<mp[i][j]);
g[id[i][j]]|=(1<<mp[i][j]);
}
}
}
dfs(cs);
if(ans==0)printf("-1");
else printf("%d",ans);
return 0;
}
对于每个x,y,z三元组,仅为只能是0或1,依次进行判断可行性
cpp
#include<bits/stdc++.h>
using namespace std;
int n,num[30],fd,j[30],vis[30];
char a[30],b[30],c[30];
bool pd(){
int f=1;
for(int i=1;i<=n;i++){
int p=num[a[i]-'A'+1],q=num[b[i]-'A'+1],r=num[c[i]-'A'+1];
if(p&&q&&r){
if(f){
if((p+q+j[i-1]-2)%n!=r-1)return 0;
j[i]=(p+q+j[i-1]-2)/n;
}
else{
if((p+q+1-2)%n!=r-1&&(p+q-2)%n!=r-1)return 0;
}
}
else{
f=0;
}
}
return 1;
}
void dfs(int x){
if(fd)return ;
if(x==n+1){
for(int i=1;i<=n;i++){
printf("%d ",num[i]-1);
}fd=1;
return ;
}
int p=num[a[x]-'A'+1],q=num[b[x]-'A'+1],r=num[c[x]-'A'+1];
//printf("%d %d %d\n",p,q,r);
if(p&&q&&r){
if(pd())dfs(x+1);
}
else if(p&&q){
if(!vis[(p+q+j[x-1]-2)%n+1]){
num[c[x]-'A'+1]=(p+q+j[x-1]-2)%n+1;
vis[(p+q+j[x-1]-2)%n+1]=1;
if(pd())dfs(x+1);
vis[(p+q+j[x-1]-2)%n+1]=0;;
num[c[x]-'A'+1]=0;
}
}
else if(p&&r){
if(!vis[(n*2+r-j[x-1]-p)%n + 1] ){
num[b[x]-'A'+1]=(n*2+r-j[x-1]-p)%n+1;
vis[(n*2+r-j[x-1]-p)%n+1]=1;
if(pd())dfs(x+1);
vis[(n*2+r-j[x-1]-p)%n+1]=0;
num[b[x]-'A'+1]=0;
}
}
else if(q&&r){
if(!vis[(n*2+r-j[x-1]-q)%n+1]){
num[a[x]-'A'+1]=(n*2+r-j[x-1]-q)%n+1;
vis[(n*2+r-j[x-1]-q)%n+1]=1;
if(pd())dfs(x+1);
vis[(n*2+r-j[x-1]-q)%n+1]=0;
num[a[x]-'A'+1]=0;
}
}
else if(!p){
for(int i=1;i<=n;i++){
if(!vis[i]){
num[a[x]-'A'+1]=i;
vis[i]=1;
if(pd())dfs(x);
vis[i]=0;
num[a[x]-'A'+1]=0;
}
}
}
else if(!q){
for(int i=1;i<=n;i++){
if(!vis[i]){
num[b[x]-'A'+1]=i;
vis[i]=1;
if(pd())dfs(x);
vis[i]=0;
num[b[x]-'A'+1]=0;
}
}
}
}
int main(){
scanf("%d%s%s%s",&n,a+1,b+1,c+1);
for(int i=1;i<=n/2;i++)swap(a[i],a[n-i+1]);
for(int i=1;i<=n/2;i++)swap(b[i],b[n-i+1]);
for(int i=1;i<=n/2;i++)swap(c[i],c[n-i+1]);
dfs(1);
return 0;
}
纯模拟,hash记录状态
cpp
#include<bits/stdc++.h>
using namespace std;
const int n=5,m=7;
int mp[10][10],lim,fd,d[100005][10][10],tot,bj[10][10],h[10][10];
unordered_map<unsigned long long,bool>M[7];
void print(){for(int j=m;j>=1;j--){
for(int i=1;i<=n;i++){
printf("%d ",mp[i][j]);
}puts("");}
puts("");
}
struct S{
int x,y,f;
}a[6];
bool check(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j])return 0;
}
}
return 1;
}
void hs(int t){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]=d[t][i][j];
}
}
}
int gx(){
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)bj[i][j]=0;
for(int i=1;i<=n;i++){
for(int j=2;j<=m;j++){
int x=i,y=j;
while(y-1>=1&&mp[x][y]&&mp[x][y-1]==0){
swap(mp[x][y],mp[x][y-1]);
y--;
}
}
}
int f=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i-1>=1&&i+1<=n&&mp[i][j]&&mp[i+1][j]&&mp[i-1][j]&&mp[i][j]==mp[i+1][j]&&mp[i][j]==mp[i-1][j]){
f=0;bj[i][j]=bj[i+1][j]=bj[i-1][j]=1;//cout<<i<<" "<<j<<endl;
}
if(j-1>=1&&j+1<=m&&mp[i][j]&&mp[i][j-1]&&mp[i][j+1]&&mp[i][j]==mp[i][j+1]&&mp[i][j]==mp[i][j-1]){
f=0;bj[i][j]=bj[i][j+1]=bj[i][j-1]=1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(bj[i][j]==1)mp[i][j]=0;
}
}
if(!f)gx();
return f;
}
bool pd(int x){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
h[i][j]=h[i-1][j]*1331+h[i][j-1]*131-h[i-1][j-1]*131*1331+mp[i][j]+1;
}
}
if(M[x][h[n][m]]){
return 0;
}
else{
M[x][h[n][m]]=1;
return 1;
}
}
void dfs(int x){
//print();
if(fd)return ;
if(check()){
if(x==lim+1){
for(int i=1;i<=lim;i++){
printf("%d %d %d\n",a[i].x-1,a[i].y-1,a[i].f);
}
fd=1;
}
return ;
}
if(x==lim+1)return;
int t=++tot;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
d[t][i][j]=mp[i][j];
}
}
int f;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]){
if(i!=n){
swap(mp[i][j],mp[i+1][j]);
gx();
a[x]={i,j,1};
if(pd(x))dfs(x+1);
hs(t);
}
if(i!=1){
swap(mp[i][j],mp[i-1][j]);
gx();
a[x]={i,j,-1};
if(pd(x))dfs(x+1);
hs(t);
}
}
}
}
}
int main(){
cin>>lim;
for(int i=1;i<=n;i++){
for(int j=1;j<=m+1;j++){
scanf("%d",&mp[i][j]);
if(!mp[i][j])break;
}
}
dfs(1);
if(!fd)printf("%d",-1);
return 0;
}
二.迭代加深

cpp
#include<bits/stdc++.h>
using namespace std;
int n,cab[105],fd;
void dfs(int x,int lim){
int mp[105]={0};
if(fd)return;
if(cab[x-1]==n){
for(int i=1;i<x;i++){
printf("%d ",cab[i]);
}
printf("\n");
fd=1;return;
}
if(x>lim)return;
for(int i=x-1;i>=1;i--){
for(int j=i;j>=1;j--){
if(cab[i]+cab[j]<=n&&mp[cab[i]+cab[j]]==0&&cab[i]+cab[j]>cab[x-1]){
cab[x]=cab[i]+cab[j];
mp[cab[i]+cab[j]]=1;
dfs(x+1,lim);
}
}
}
}
int main(){
while(scanf("%d",&n)&&n){
if(n==1){
printf("1\n");
continue;
}
fd=0;
cab[1]=1;
for(int i=2;i<=n;i++){
dfs(2,i);
if(fd)break;
}
}
return 0;
}
*先预处理出所有可能的数列,然后进行拼凑,化指数为组合
考虑剪枝:
1.优化搜索顺序:按点的个数对数列排序,
2.排除等效冗余:若后面几层都假设放最多还达不到n,直接回溯、
3.迭代加深
cpp
#include<bits/stdc++.h>
using namespace std;
int n,bus[70],fd;
struct S{
int n,a,d;
};
vector<S>f;
bool check(int a,int d){
for(int i=a;i<60;i+=d)if(!bus[i])return 0;
return 1;
}
bool cmp(S a,S b){
return a.n>b.n;
}
void dfs(int dep,int k,int num){
//cout<<dep<<" "<<k<<" "<<num<<endl;
if(fd==1)return;
if(!dep){
if(num==n)fd=1;
return;
}
for(int i=k;i<f.size();i++){
if(!check(f[i].a,f[i].d))continue;
if(f[i].n*dep+num<n)continue;
for(int j=f[i].a;j<60;j+=f[i].d)bus[j]--;
dfs(dep-1,i,num+f[i].n);
for(int j=f[i].a;j<60;j+=f[i].d)bus[j]++;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);bus[x]++;
}
for(int a=0;a<60;a++){
for(int d=a+1;d+a<60;d++){
if(check(a,d))f.push_back({(59-a)/d+1,a,d});
}
}
sort(f.begin(),f.end(),cmp);
for(int i=1;i<=17;i++){
dfs(i,0,0);
if(fd){
printf("%d",i);
break;
}
}
return 0;
}
首先,对于每一个数,要不up[],要不down[],两种分支
其次,想到贪心,以up[]为例,如果能放则放(这个当时没想到),而且接在最大的能接的后面
最后,迭代加深即可
cpp
#include<bits/stdc++.h>
using namespace std;
int n,a[55];
int up[55],down[55],t1,t2;
bool dfs(int x,int lim){
if(t1+t2>lim)return 0;
if(x==n+1)return 1;
int m=0,id=0;
for(int i=1;i<=t1;i++){
if(up[i]<a[x]&&up[i]>m){
m=up[i],id=i;
}
}
if(id){
up[id]=a[x];
if(dfs(x+1,lim))return 1;
up[id]=m;
}
else{
up[++t1]=a[x];
if(dfs(x+1,lim))return 1;
t1--;
}
m=1e9,id=0;
for(int i=1;i<=t2;i++){
if(down[i]>a[x]&&m>down[i]){
m=down[i],id=i;
}
}
if(id){
down[id]=a[x];
if(dfs(x+1,lim))return 1;
down[id]=m;
}
else{
down[++t2]=a[x];
if(dfs(x+1,lim))return 1;
t2--;
}
return 0;
}
int main(){
while(~scanf("%d",&n)&&n){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
if(dfs(1,i)){
t1=0,t2=0;
printf("%d\n",i);
//print();
break;
}
}
}
return 0;
}
三、双向搜索
先搜前一段,后一段二分查找匹配
attention:lowerbound满
cpp
#include<bits/stdc++.h>
using namespace std;
long long w,n,cnt[1<<25],a[50],k,tot,ans;
long long erf(long long x){
int l=1,r=tot,res;
while(l<=r){
int mid=(l+r)>>1;
if(x+cnt[mid]<=w){
l=mid+1;
res=mid;
}
else{
r=mid-1;
}
}
return cnt[res];
}
void dfs(int x,long long v){
if(x==k+1){
cnt[++tot]=v;return ;
}
if(a[x]+v<=w){
dfs(x+1,a[x]+v);
}
dfs(x+1,v);
}
void dfs2(int x,long long v){
if(x==n+1){
ans=max(ans,v+erf(v));
return ;
}
if(a[x]+v<=w){
dfs2(x+1,a[x]+v);
}
dfs2(x+1,v);
}
int main(){
scanf("%lld%lld",&w,&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
k=n/2;
dfs(1,0);
sort(cnt+1,cnt+tot+1);
tot=unique(cnt+1,cnt+tot+1)-cnt-1;
dfs2(k+1,0);
printf("%lld",ans);
return 0;
}