HDU 5727 Necklace
题目:Necklace
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5727
题意:要用n个阳石和n个阴石来串一个项链(环状),规定阳石旁边只能是阴石,阴石旁只能是阳石,现在有m对特殊阴阳石,这些阴阳石相邻会使得阳石出故障(照样可以用),问串这个项链,至少有几个故障的阳石。
思路:
看到题目的瞬间,莫名奇妙地就想到了二分图(阴石和阳石两个集合,又要求阴阳交错着放),有个变通就是最后并不是阴石匹配阳石,而是阳石去匹配位置,看最多几个位置能放上阳石...
我们可以先枚举所有的阴石排法(全排列),然后用二维数组s来表示阳石i可以放在哪些位置,s[i][j]=1表示阳石i可以放在j处,前提是j的两旁没有克制阳石i的阴石。这样,位置和阳石就成了两个集合,我们要做的就是让尽量多的位置放了阳石,(这种阴石排法最终故障数就是n-位置数(最大匹配数))。这道题时间卡得很紧,有一个很重要的剪枝就是全排列过程中如果最终故障数已经为0,就return吧,就不要再尝试新的排法了。
我的代码是勉强过的,有待改进,看到网上有个自动全排列的函数next_permutation,准备去学下,我试过,比自己深搜递归快,下面两个版本,第一个1400ms左右,第二个200ms左右,快太多了,(除了本身快以外,我还少排了一个数,因为项链是一个环,所以完全可以固定一个数的位置,这样就少了一级。)
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<vector> 5 using namespace std; 6 int n,m,maxt; 7 int mp[12][12]; 8 vector<int> s[12]; 9 int b[12]; 10 bool u[12]; 11 bool find(int x) 12 { 13 if(u[x]) return false; 14 u[x]=1; 15 for(int j=0;j<s[x].size();j++) 16 { 17 int i=s[x][j]; 18 if(b[i]==0||find(b[i])) 19 { 20 b[i]=x; 21 return true; 22 } 23 } 24 return false; 25 } 26 void solve() 27 { 28 memset(b,0,sizeof(b)); 29 int co=0; 30 for(int i=1;i<=n;i++) 31 { 32 memset(u,0,sizeof(u)); 33 if(find(i)) co++; 34 } 35 if(co>maxt) maxt=co; 36 } 37 bool v[12]; 38 int aa[12]; 39 void dfs(int ceng) 40 { 41 if(ceng==n) 42 { 43 for(int i=1;i<=n;i++) s[i].clear(); 44 for(int i=0;i<n;i++) 45 { 46 int k=aa[i],kk=aa[(i-1+n)%n]; 47 for(int j=1;j<=n;j++) 48 { 49 if(mp[k][j]==-1&&mp[kk][j]==-1) s[j].push_back(i); 50 } 51 } 52 solve(); 53 return ; 54 } 55 for(int i=1;i<=n&&maxt!=n;i++) 56 { 57 if(v[i]==1) continue; 58 v[i]=1; 59 aa[ceng]=i; 60 dfs(ceng+1); 61 v[i]=0; 62 } 63 } 64 int main() 65 { 66 int x,y; 67 while(scanf("%d%d",&n,&m)!=EOF) 68 { 69 maxt=0; 70 memset(mp,-1,sizeof(mp)); 71 while(m--) 72 { 73 scanf("%d%d",&x,&y); 74 mp[y][x]=0; 75 } 76 memset(v,0,sizeof(v)); 77 dfs(0); 78 printf("%d\n",n-maxt); 79 } 80 return 0; 81 }
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<vector> 5 #include<algorithm> 6 using namespace std; 7 int n,m,maxt; 8 int mp[12][12]; 9 vector<int> s[12]; 10 int b[12]; 11 bool u[12]; 12 bool find(int x) 13 { 14 if(u[x]) return false; 15 u[x]=1; 16 for(int j=0;j<s[x].size();j++) 17 { 18 int i=s[x][j]; 19 if(b[i]==0||find(b[i])) 20 { 21 b[i]=x; 22 return true; 23 } 24 } 25 return false; 26 } 27 void solve() 28 { 29 memset(b,0,sizeof(b)); 30 int co=0; 31 for(int i=1;i<=n;i++) 32 { 33 memset(u,0,sizeof(u)); 34 if(find(i)) co++; 35 } 36 if(co>maxt) maxt=co; 37 } 38 bool v[12]; 39 int aa[12]; 40 void dfs(int ceng) 41 { 42 for(int i=0;i<n;i++) 43 { 44 aa[i]=i+1; 45 } 46 do 47 { 48 for(int i=1;i<=n;i++) s[i].clear(); 49 for(int i=0;i<n;i++) 50 { 51 int k=aa[i],kk=aa[(i-1+n)%n]; 52 for(int j=1;j<=n;j++) 53 { 54 if(mp[k][j]==-1&&mp[kk][j]==-1) s[j].push_back(i); 55 } 56 } 57 solve(); 58 }while(next_permutation(aa+1,aa+n)&&maxt!=n); 59 } 60 int main() 61 { 62 int x,y; 63 while(scanf("%d%d",&n,&m)!=EOF) 64 { 65 maxt=0; 66 memset(mp,-1,sizeof(mp)); 67 while(m--) 68 { 69 scanf("%d%d",&x,&y); 70 mp[y][x]=0; 71 } 72 memset(v,0,sizeof(v)); 73 dfs(0); 74 printf("%d\n",n-maxt); 75 } 76 return 0; 77 }