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 } 用了next_permutation?
轉載于:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5690008.html
總結
以上是生活随笔為你收集整理的HDU 5727 Necklace的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 他是一片温暖的湖泊高告诉了我们什么?
- 下一篇: Android Handler主线程和一