全排列框架:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=100;
int a[NM],n;
void Perm(int k)
{
int i;
if(k==n){
for(i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
else{
for(i=k;i<=n;i++){
swap(a[k],a[i]);
Perm(k+1);
swap(a[k],a[i]);
}
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
a[i]=i;
Perm(1);
}
return 0;
}
5.2 装载问题
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=100;
int wi[NM],path[NM],x[NM],n,bestmax,Wleft,c;
void Backtrack(int cw,int i)
{
if(i>n){
bestmax=cw;
for(int j=1;j<=n;j++)
path[j]=x[j];
return;
}
Wleft-=wi[i];
if(cw+wi[i]<=c){ //x[i]=1;
x[i]=1;
Backtrack(cw+wi[i],i+1);
}
if(cw+Wleft>bestmax){ //x[i]=0;
x[i]=0;
Backtrack(cw,i+1);
}
Wleft+=wi[i]; //
}
int main()
{
int t,i;
while(~scanf("%d%d",&n,&c))
{
Wleft=bestmax=0;
for(i=1;i<=n;i++){
scanf("%d",&wi[i]);
Wleft+=wi[i];
}
t=Wleft;
Backtrack(0,1);
for(i=1;i<=n;i++)
printf("%d ",path[i]);
printf("\nbestmax: %d\n",bestmax);
if(t-bestmax<=c) printf("YES\n");
else printf("NO\n");
}
return 0;
}
/*
3 50
10 40 40
3 50
20 40 40
6 100
10 20 30 30 20 40
6 125
40 40 50 50 30 40
*/
5.3 批作业处理调度
#include <iostream>
#include <cstdio>
using namespace std;
const int NM=25;
int M[NM][3],b[NM],f2[NM],x[NM],n,bestmax,f1,f;
void Backtrack(int t)
{
if(t>n){
for(int i=1;i<=n;i++)
b[i]=x[i];
bestmax=f;return;
}
for(int j=t;j<=n;j++){
f1+=M[x[j]][1];
f2[t]=(f1>f2[t-1]?f1:f2[t-1])+M[x[j]][2];
f+=f2[t];
if(f<bestmax){
swap(x[t],x[j]);
Backtrack(t+1);
swap(x[t],x[j]);
}
f-=f2[t];
f1-=M[x[j]][1];
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++){
scanf("%d%d",&M[i][1],&M[i][2]);
x[i]=i;f2[i]=0;
}
bestmax=0xfffffff;
f1=f=0;
Backtrack(1);
for(i=1;i<=n;i++)
cout<<b[i]<<" ";
cout<<endl;
printf("%d\n",bestmax);
}
return 0;
}
/*
3
2 1
3 1
2 3
3
2 2
1 1
3 3
*/
5.4 符号三角形
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=100;
int half,sum,cc,n,a[NM][NM];
void Backtrack(int t)
{
int i,j;
if(cc>half || t*(t-1)/2-cc>half) return; //(t-1+1)*(t-1)/2
if(t>n) sum++;
else{
for(i=0;i<2;i++){
cc+=i;
a[1][t]=i;
for(j=2;j<=t;j++){
a[j][t-j+1]=a[j-1][t-j+1]^a[j-1][t-j+2];
cc+=a[j][t-j+1];
}
Backtrack(t+1);
for(j=2;j<=t;j++)
cc-=a[j][t-j+1];
cc-=i;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
half=n*(1+n)/2;
if(half%2!=0){
printf("0\n");
continue;
}
half/=2;
sum=cc=0;
memset(a,0,sizeof(a));
Backtrack(1);
printf("%d\n",sum);
}
return 0;
}
5.5 n皇后问题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int NM=25;
int sum,n,y[NM],save[NM];
bool check(int t)
{
for(int j=1;j<t;j++){
if((abs(t-j)==abs(y[t]-y[j]) ||y[t]==y[j]))
return false;
}
return true;
}
void Backtrack(int t) //t-->x
{
if(t>n) {
sum++;return;
}
for(int i=1;i<=n;i++){
y[t]=i; //y[i]-->y
if(check(t)) Backtrack(t+1);
}
}
int main()
{
for(int i=1;i<=10;i++){
n=i;sum=0;
Backtrack(1);
save[i]=sum;
}
while(scanf("%d",&n) && n){
printf("%d\n",save[n]);
}
return 0;
}
5.6 0-1背包问题
注:未加Bound()函数
#include <iostream>
#include <cstdio>
using namespace std;
const int NM=100;
int wei[NM],vau[NM],ans,n;
void DFS(int i,int wi,int vi)
{
if(i>n) return;
if(vi>ans) ans=vi;
if(wi>=wei[i]){
DFS(i+1,wi-wei[i],vi+vau[i]); //1
}
DFS(i+1,wi,vi); //0
}
int main()
{
int V,i;
while(~scanf("%d%d",&n,&V))
{
for(i=0;i<n;i++){
scanf("%d%d",&wei[i],&vau[i]);
}
ans=0;
DFS(0,V,0);
printf("%d\n",ans);
}
return 0;
}
5.7 旅行售货员
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=25;
int a[NM][NM],x[NM],path[NM],n,bestmax,cost;
void Backtrack(int t)
{
if(t==n){
int temp=cost+a[x[n-1]][x[n]]+a[x[n]][1];
if(a[x[n-1]][x[n]] && a[x[n]][1] && temp<bestmax){
bestmax=temp;
for(int j=1;j<=n;j++)
path[j]=x[j];
}
return;
}
for(int i=t;i<=n;i++){
if(a[x[t-1]][x[i]] && cost+a[x[t-1]][x[i]]<bestmax){
swap(x[t],x[i]);
cost+=a[x[t-1]][x[t]]; //
Backtrack(t+1);
cost-=a[x[t-1]][x[t]];
swap(x[t],x[i]);
}
}
}
int main()
{
int A,B,i,vau,m;
while(scanf("%d%d",&n,&m) && n){
for(i=1;i<=n;i++)
x[i]=i;
memset(a,0,sizeof(a));
for(i=0;i<m;i++){
scanf("%d%d%d",&A,&B,&vau);
a[A][B]=a[B][A]=vau;
}
bestmax=0xfffffff;cost=0;
Backtrack(2); /*搜索x[2:n]全排列*/
printf("%d\n",bestmax);
for(i=1;i<=n;i++)
printf("%d ",path[i]);
printf("\n");
}
return 0;
}
/*
4 6
1 2 30
1 3 6
1 4 4
2 3 5
2 4 34
3 4 2
*/
5.8 图的着色问题
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=105;
int a[NM][NM],x[NM],sum,color,n;
bool check(int t)
{
for(int j=1;j<=n;j++){ /*这里和n皇后问题不一样*/
if(a[t][j] && x[j]==x[t]) return false;
}
return true;
}
void Backtrack(int t)
{
if(t>n) {
sum++;
for(int i=1;i<=n;i++)
printf("%d ",x[i]);
printf("\n");
return;
}
for(int j=1;j<=color;j++){
x[t]=j;
if(check(t)) Backtrack(t+1);
x[t]=0; //每一个点都可以着不同的颜色
}
}
int main()
{
int m,i,x1,y1;
while(~scanf("%d%d%d",&n,&m,&color))
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
for(i=0;i<m;i++){
scanf("%d%d",&x1,&y1);
a[x1][y1]=a[y1][x1]=1;
}
sum=0;
Backtrack(1);
if(sum>0) printf("Yes %d\n",sum);
else printf("No\n");
}
return 0;
}
/*
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
*/