(一)简单枚举
1. pair && UVA 10976 分数拆分
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
int n;
int main()
{
while(~scanf("%d",&n))
{
int ans=0;
typedef pair<int,int> P;
vector<P> vans;
for(int y=n+1;y<=2*n;y++)
if(n*y%(y-n)==0)
{
int x=n*y/(y-n);
ans++;
vans.push_back(P(x,y));
}
cout<<ans<<endl;
for(int i=0;i<ans;i++)
printf("1/%d = 1/%d + 1/%d\n",n,vans[i].first,vans[i].second);
}
return 0;
}
2. 进制
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
bool check(int x,int k)
{
vector<int> va;
int num=0;
while(x>0)
{
va.push_back(x%k);
x=x/k;
num++;
}
for(int i=0; i<num; i++)
if(va[i]!=va[num-1-i])
return false;
return true;
}
int main()
{
int n;
while(cin>>n)
{
for(;; n++)
{
int c=0,k;
for(k=2; k<=10; k++)
{
if(check(n,k))
c++;
if(c>=2)
break;
}
if(k<=10)
{
cout<<n<<endl;
break;
}
}
}
return 0;
}
(二)枚举排列
1. 生成可重集的排列
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n,a[100],t[100];
void print_per(int cur)
{
if(cur==n)
{
for(int i=0; i<n; i++)
cout<<a[i];
cout<<endl;
return;
}
for(int i=0; i<n; i++)
{
if(!i||t[i]!=t[i-1])
{
int c1=0,c2=0;
for(int j=0; j<cur; j++)
if(t[i]==a[j])
c1++;
for(int j=0; j<n; j++)
if(t[i]==t[j])
c2++;
if(c1<c2)
{
a[cur]=t[i];
print_per(cur+1);
}
}
}
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>t[i];
sort(t,t+n);
print_per(0);
}
return 0;
}
2.next_permutation
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>t[i];
sort(t,t+n);
do
{
for(int i=0;i<n;i++)
cout<<t[i];
cout<<endl;
}while(next_permutation(t,t+n));
}
return 0;
}
3、子集的生成
(1)增量构造法
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n,t[100],ans[100];
void solve(int cur,int tpre)
{
for(int i=0; i<cur; i++)
{
cout<<ans[i];
if(i==cur-1)
cout<<endl;
}
//int s=cur?tpre+1:0;
for(int i=tpre+1; i<n; i++)
{
ans[cur]=t[i];
solve(cur+1,i);
}
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>t[i];
sort(t,t+n);
solve(0,-1);
}
return 0;
}
(2)位向量法
vis[i]=1表示选中t[i]这个数
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n,t[100],vis[100];
void solve(int cur)
{
if(cur==n)
{
for(int i=0;i<n;i++)
if(vis[i])
cout<<t[i];
cout<<endl;
return;
}
vis[cur]=1;
solve(cur+1);
vis[cur]=0;
solve(cur+1);
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>t[i];
sort(t,t+n);
memset(vis,0,sizeof(vis));
solve(0);
}
return 0;
}
(3)二进制法
0~n-1的子集
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n;
void subset(int s)
{
int flag=0;
for(int i=0; i<n; i++)
if(s&(1<<i)) //判断n的第i位是否为1
{
cout<<i;
flag=1;
}
if(flag)
cout<<endl;
}
int main()
{
while(cin>>n)
{
for(int i=0; i<(1<<n); i++)//1左移n位等价于2^n-1.因为子集个数2^n-1
subset(i);
}
return 0;
}
(三)回溯法
(1)困难的串
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int L,n,cnt,ans[100];
int solve(int cur)
{
if(cnt++==n)
{
for(int i=0; i<cur; i++)
printf("%c",'A'+ans[i]);
cout<<endl;
return 0;
}
for(int i=0; i<L; i++)
{
ans[cur]=i;
int flag=1;
for(int j=1;j*2<=cur+1;j++)//循环判断长度长度为j*2的后缀
{
int iequal=1;//判断后缀中是否有前一半是否等于后一半
for(int k=0;k<j;k++)
if(ans[cur-k]!=ans[cur-k-j])//只要确定了后缀j*2中有一个不相等,则可以确定前一半与后一半不相等
{
iequal=0;
break;
}
if(iequal)
{
flag=0;
break;
}
}
if(flag)
if(!solve(cur+1)) return 0;
}
return 1;
}
int main()
{
int t=0;
while(cin>>n>>L)
{
if(t++) cout<<endl;
cnt=0;
solve(0);
}
return 0;
}
(2)带宽
UVA 140
刘汝佳老师的源码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
/*
A:FB;B:GC;D:GC;F:AGH;E:HD
#
*/
int main()
{
char input[205];
int id[256],letter[10];
while(~scanf("%s",input)&&input[0]!='#')
{
// 计算结点个数并给字母编号
int n=0;
for(char ch='A'; ch<='Z'; ch++)
{
if(strchr(input,ch)!=NULL)
{
id[ch]=n++; //下标'A'->66
letter[id[ch]]=ch;
}
}
int p=0,q=0;
int len=strlen(input);
vector<int> u,v;
while(1)
{
while(p<len&&input[p]!=':') p++;
if(p==len) break;
while(q<len&&input[q]!=';') q++;
for(int i=p+1;i<q;i++)
{
u.push_back(id[input[p-1]]);
v.push_back(id[input[i]]);
}
p++;q++;
}
// 枚举全排列
int P[10],bestP[10],pos[10],ans=n;
for(int i=0;i<n;i++) P[i]=i; //i指第i个
do
{
for(int i=0;i<n;i++) pos[P[i]]=i;
int wide=0;
for(int i=0;i<(int)u.size();i++)
{
wide=max(wide,abs(pos[u[i]]-pos[v[i]]));
if(wide>=ans)
break;
}
if(wide<ans)
{
ans=wide;
memcpy(bestP,P,sizeof(P));
}
}while(next_permutation(P,P+n));
for(int i=0;i<n;i++)
printf("%c ",letter[bestP[i]]);
cout<<"-> "<<ans<<endl;
}
return 0;
}