题意:《算法竞赛入门》 196页
思路 : 输入比较特殊,其他正常可以暴力枚举全排列。中间考虑剪枝,在搜索的过程出现的最大带宽比已有还要大就return。但是这题数据太弱了,不剪29ms,剪枝0ms.
由于是全排列问题,也可以直接调用next_permutation()函数简化代码。
dfs无剪枝
#include<bits/stdc++.h>
using namespace std;
int M[26][26],alh[30],node[10],ans[10],cnt,_max,a[10],v[10];
const int inf=0x7fffffff;
string s;
void dfs(int cur)
{
if(cur==cnt){
int num=0;
for(int i=0;i<cnt;i++){
for(int j=i+1;j<cnt;j++){
if(M[a[i]][a[j]]&&abs(i-j)>num){
num=abs(i-j);
}
}
}
if(num>=_max) return;
_max=num;
for(int i=0;i<cnt;i++) ans[i]=a[i];
return;
}
for(int i=0;i<cnt;i++){
if(!v[i]){
a[cur]=node[i];
v[i]=1;
dfs(cur+1);
v[i]=0;
}
}
}
int main()
{
while(getline(cin,s)){
if(s[0]=='#') break;
int len=s.size(),c,flag=0;
memset(alh,0,sizeof(alh));
memset(M,0,sizeof(M));
for(int i=0;i<len;i++){
if(s[i]>='A'&&s[i]<='Z'){
alh[s[i]-'A']=1;
}
if(s[i]==':'){
c=s[i-1]-'A';
flag=1;
}
else if(flag&&s[i]>='A'&&s[i]<='Z'){
M[c][s[i]-'A']=M[s[i]-'A'][c]=1;
}
else if(s[i]==';') flag=0;
}
cnt=0;
for(int i=0;i<26;i++){
if(alh[i]) node[cnt++]=i;
}
_max=inf;
memset(v,0,sizeof(v));
dfs(0);
for(int i = 0; i < cnt; i++)
printf("%c ", ans[i] + 'A');
printf("-> %d\n", _max);
}
}
dfs剪枝
#include<bits/stdc++.h>
using namespace std;
int M[26][26],alh[30],node[10],ans[10],cnt,_max,a[10],v[10];
const int inf=0x7fffffff;
string s;
void dfs(int cur,int cw)
{
if(cur==cnt){
_max=cw;
for(int i=0;i<cnt;i++) ans[i]=a[i];
return;
}
for(int i=0;i<cnt;i++){
if(!v[i]){
a[cur]=node[i];
v[i]=1;
int t=0;
for(int j=0;j<cur;j++){
if(M[node[i]][a[j]]&&abs(cur-j)>t){
t=abs(cur-j);
}
}
int w=max(cw,t);
if(w<_max)
dfs(cur+1,w);
v[i]=0;
}
}
}
int main()
{
while(getline(cin,s)){
if(s[0]=='#') break;
int len=s.size(),c,flag=0;
memset(alh,0,sizeof(alh));
memset(M,0,sizeof(M));
for(int i=0;i<len;i++){
if(s[i]>='A'&&s[i]<='Z'){
alh[s[i]-'A']=1;
}
if(s[i]==':'){
c=s[i-1]-'A';
flag=1;
}
else if(flag&&s[i]>='A'&&s[i]<='Z'){
M[c][s[i]-'A']=M[s[i]-'A'][c]=1;
}
else if(s[i]==';') flag=0;
}
cnt=0;
for(int i=0;i<26;i++){
if(alh[i]) node[cnt++]=i;
}
_max=inf;
memset(v,0,sizeof(v));
dfs(0,0);
/* do { int num=0; for(int i = 0; i < cnt; i++) for(int j = i + 1; j < cnt; j++) if(M[node[i]][node[j]]) if(abs(i - j) > num){ num = abs(i - j); //cout<<"num="<<num<<endl; } if(_max > num) { _max = num; memcpy(ans, node, sizeof(node)); } } while(next_permutation(node, node + cnt)); */
for(int i = 0; i < cnt; i++)
printf("%c ", ans[i] + 'A');
printf("-> %d\n", _max);
}
}
next_permution()无剪枝
#include<bits/stdc++.h>
using namespace std;
int M[26][26],alh[30],node[10],ans[10],cnt,_max,a[10],v[10];
const int inf=0x7fffffff;
string s;
int main()
{
while(getline(cin,s)){
if(s[0]=='#') break;
int len=s.size(),c,flag=0;
memset(alh,0,sizeof(alh));
memset(M,0,sizeof(M));
for(int i=0;i<len;i++){
if(s[i]>='A'&&s[i]<='Z'){
alh[s[i]-'A']=1;
}
if(s[i]==':'){
c=s[i-1]-'A';
flag=1;
}
else if(flag&&s[i]>='A'&&s[i]<='Z'){
M[c][s[i]-'A']=M[s[i]-'A'][c]=1;
}
else if(s[i]==';') flag=0;
}
cnt=0;
for(int i=0;i<26;i++){
if(alh[i]) node[cnt++]=i;
}
_max=inf;
do
{
int num=0;
for(int i = 0; i < cnt; i++)
for(int j = i + 1; j < cnt; j++)
if(M[node[i]][node[j]])
if(abs(i - j) > num){
num = abs(i - j);
}
if(_max > num)
{
_max = num;
memcpy(ans, node, sizeof(node));
}
}
while(next_permutation(node, node + cnt));
for(int i = 0; i < cnt; i++)
printf("%c ", ans[i] + 'A');
printf("-> %d\n", _max);
}
}
next_permutation 剪枝
#include<bits/stdc++.h>
using namespace std;
int M[26][26],alh[30],node[10],ans[10],cnt,_max,a[10],v[10];
const int inf=0x7fffffff;
string s;
void dfs(int cur,int cw)
{
if(cur==cnt){
_max=cw;
for(int i=0;i<cnt;i++) ans[i]=a[i];
return;
}
for(int i=0;i<cnt;i++){
if(!v[i]){
a[cur]=node[i];
v[i]=1;
//dfs剪枝
int t=0;
for(int j=0;j<cur;j++){
if(M[node[i]][a[j]]&&abs(cur-j)>t){
t=abs(cur-j);
break;
}
}
int w=max(cw,t);
if(w<_max)
dfs(cur+1,w);
v[i]=0;
}
}
}
int main()
{
while(getline(cin,s)){
if(s[0]=='#') break;
int len=s.size(),c,flag=0;
memset(alh,0,sizeof(alh));
memset(M,0,sizeof(M));
for(int i=0;i<len;i++){
if(s[i]>='A'&&s[i]<='Z'){
alh[s[i]-'A']=1;
}
if(s[i]==':'){
c=s[i-1]-'A';
flag=1;
}
else if(flag&&s[i]>='A'&&s[i]<='Z'){
M[c][s[i]-'A']=M[s[i]-'A'][c]=1;
}
else if(s[i]==';') flag=0;
}
cnt=0;
for(int i=0;i<26;i++){
if(alh[i]) node[cnt++]=i;
}
_max=inf;
// memset(v,0,sizeof(v));
//dfs(0,0);
do
{
int num=0;
for(int i = 0; i < cnt; i++){
for(int j = i + 1; j < cnt; j++){
if(M[node[i]][node[j]]){
if(abs(i - j) > num){
num = abs(i - j);
//cout<<"num="<<num<<endl;
}
}
}
if(num>_max) break;
}
if(_max > num)
{
_max = num;
memcpy(ans, node, sizeof(node));
}
}
while(next_permutation(node, node + cnt));
for(int i = 0; i < cnt; i++)
printf("%c ", ans[i] + 'A');
printf("-> %d\n", _max);
}
}