標籤:
一開始最容易想到間隔最多為n,但是結點還是太多了,需要最佳化。
剪枝1:預判一下並儲存下一個可以放的位置距離之前的距離。這樣可以減少很多判斷。
剪枝2:如果當前長度+剩下沒放的程式*最短間隔如果大於等於ans,那麼對答案沒有貢獻,可以剪去。
最佳化:佔用和不佔用兩種狀態,如果橫向來看可以壓縮為int,判斷時用上為運算。
此題掛在長度的枚舉上,我把長度為n給忽略了,實際上可以只有一部分長度為n。
#include<bits/stdc++.h>//using namespace std;//#define localconst int maxn = 20;const int N = 5;int tab[N];int ans;int ivs[maxn],SZ;void dfs(int d,int* pre,int len){ if(len + (10 - d)*ivs[0] >= ans ) return; for(int i = 0; i < SZ; i++){ int iv = ivs[i]; bool ok = true; for(int j = 0; j < N; j++) { if((pre[j]>>iv)&tab[j]) { ok = false; break;} } if(ok) { if(d == 9) { ans = std::min(ans,len+iv); return ; } int now[N]; for(int j = 0; j < N; j++) { now[j] = (pre[j] >> iv) | tab[j]; } dfs(d+1,now,len+iv); } }}void preJudge(int n){ SZ = 0; for(int iv = 1; iv <= n; iv++){ bool ok = true; for(int i = 0; i < N; i++) { if((tab[i]>>iv)&tab[i]) { ok = false; break;} } if(ok) ivs[SZ++] = iv; }}int main(){#ifdef local freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout);#endif // local int n; char G[maxn+1]; while(~scanf("%d",&n)&&n) { memset(tab,0,sizeof(tab)); for(int i = 0; i < N; i++){ scanf("%s",G); for(int j = 0; j < n; j++) if(G[j] == ‘X‘){ tab[i] |= 1<<j; } } ans = n*10; preJudge(n); dfs(1,tab,n); printf("%d\n",ans); } return 0;}
UVA 690 PipelineScheduling 位元運算+dfs+剪枝