終止狀態是從初始狀態由開關組合影響而形成的,那麼就有乙個等式使得初始狀態可以到達終止狀態,
例如a,b,c三個開關
e[a] = (xa * mp[a][a]) ^ (xb * mp[a][b]) ^ (xc*map[a][c]) ^ s[a]
e[b] = (xa * mp[b][a]) ^ (xb * mp[b][b]) ^ (xc*map[b][c]) ^ s[b]
e[c] = (xa * mp[c ][a]) ^ (xb * mp[c][b]) ^ (xc*map[c][c]) ^ s[c]
e陣列為開關的終止狀態(a,b,c為開關),s陣列為開關的初始狀態,mp[i][j] 代表j開關是否影響i開關。x為變元
根據上面的方程裝換成高斯方程組
換成矩陣形式:
mp[a][a] mp[a][b] map[a][c] e[a ]^ s[a]
mp[b][a] mp[b][b] map[b][c] e[b] ^ s[b]
mp[c ][a] mp[c][b] map[c][c] e[c] ^ s[c ]
轉換成行階梯型矩陣,然後求出矩陣的秩,矩陣的秩即為不變元的個數,剩下的就是自由元的個數。
不變元就是,我們將開關由初始狀態變為終止狀態所必須要動的開關,而自由元就是我們不一定要動的開關。
因此,我們能到達終止狀態的方案就是2的自由元次冪的個數,因為每個開關只有0,1兩種狀態。
注意求解是異或運算。
#include #include #include #include using namespace std;
#define maxn 50
int a[maxn], e[maxn];
int n;
void swap(int &a,int &b)
struct matrix
}void relax(int x, int y)
}void init()
}}m;void gauss()
}if(ptr == n+1)
if(ptr != i)
for(k = i+1; k <= n; k++ )
m.relax(i,k);//不是,則消除。}}
for( k = i; k <= n; k++)
}printf("%d\n",1<<(n-i+1));//有多少零行就有多少自由元,輸出結果
return;
}int main()
for(int i = 1; i <= n; i++)
while(scanf("%d%d",&s,&t),s|t)
gauss();
}return 0;
}
POJ 1830 開關問題 高斯消元
開關問題 time limit 1000ms memory limit 30000k total submissions 3390 accepted 1143 description 有n個相同的開關,每個開關都與某些開關有著聯絡,每當你開啟或者關閉某個開關的時候,其他的與此開關相關聯的開關也會相應...
poj 1830 開關問題 高斯消元
題意是 給一些開關的初始狀態 0 或1 在給出終止狀態,在給出相關的變化規則,規則 x 變化 則 y 也變 x y 讀入。輸出有多少種開關的撥動情況,使初始狀態變成終止狀態。此問題 很容易轉化成 高斯消元 解 異或方程組。t 方程組的自由化的個數,則結果就是 2 t include include ...
poj 1830 開關問題 高斯消元
題意 給出一些開關互相影響的關係,問從開關的初始狀態到結束狀態有多少種變換的方法。題解 對於每個開關可能會受1.i某寫開關的影響,因此對於開關i列出乙個列向量,列向量每個元素只有1或0,表示某個開關是否影響這個i開關,這樣就n個開關組合成乙個矩陣,結束狀態也是乙個列向量,這樣就可以用高斯消元求解解的...