|——-| |——-| |——-|
| | | | | | |
|—o | |—o | | o |
| | | | | |
|——-| |——-| |——-|
a b c
|——-| |——-| |——-|
| | | | | |
| o | | o | | o |
| | | | | | | | |
|——-| |——-| |——-|
d e f
|——-| |——-| |——-|
| | | | | |
| o | | o—| | o |
| | | | | | | |
|——-| |——-| |——-|
g h i
(figure 1)`
move affected clocks
1 abde
2 abc
3 bcef
4 adg
5 bdefh
6 cfi
7 degh
8 ghi
9 efhi
(figure 2)
your program is to read from standard input. nine numbers give the start positions of the dials. 0=12 o』clock, 1=3 o』clock, 2=6 o』clock, 3=9 o』clock.
your program is to write to standard output. output a shortest sorted sequence of moves (numbers), which returns all the dials to 12 o』clock. you are convinced that the answer is unique.
3 3 0
2 2 2
2 1 2
4 5 8 9
這題只有9個鐘 每個鐘可以轉0~3次 所以49
4
9列舉也可行?
但這題是乙個解方程組的思路
可以做到93
9
3的時間複雜度
先確定初末狀態
輸入給的是初始狀態
對於末狀態 我們要使得所有鐘錶歸零
我們要求解的未知數x1~x9代表9種操作所做的次數 範圍是0~3 因為做四次等於沒做
而對於係數矩陣 行號i代表第i個鐘錶會被ai
jwhi
chis
1 aij
whic
his1
的操作影響
這樣增廣矩陣的右邊列向量 代表對於每個鐘需要幾次操作(由初末狀態求得、套路)
mod4
取模操作很關鍵
如果用浮點型的高斯消元,顯然不能取模(或者說很不方便,①有精度問題 ②這裡保證整數解,沒必要浮點 ③整數取模方便)
所以採用整數的形式
如何行變換相消去呢?
採用公倍數的形式
對於最後求未知數(ans陣列)
可以採用兩種方式
1.若矩陣化成的是對角型 則可以直接求解(若取模,則要求逆元;若模數很小,可以直接迴圈,如本題)
2.若矩陣化成的是上三角型 則回代法求解(若取模,則要求逆元;若模數很小,可以直接迴圈,如本題)
//高斯消元 時間複雜度o(n^3) 使用整型計算
//公倍數法 適用於只需要整數解、取模的情況
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int maxn=101;
long
long det;//行列式的值
int mod;
//特別適合於行列式求值 取模操作 (除法要求逆元)
//不化成對角而是上三角 因為涉及到取模 要保留一些資訊
inline
int solve(int a[maxn],bool l,int ans,const
int &n,const
int &m)
//從a[r][i]這乙個元素開始 往下的每個元素都是0了 所以這個元素xi是自由變元 i+1跳過即可
if(a[r][i]==0)
for(int j=0;j//j是行數 從0開始 是對角 不是上三角 這樣不要從下往上回代
if(j!=r&&a[j][i])
}l[i]=true,++r;
}//輸出階梯型矩陣
// for(int j=0;j
// for(int k=0;k<=n;++k)
// coutdet=1;
for(int i=0;i//檢查是否無解
for(int i=n-res;iif(a[i][n]) return -1;
}for(int i=0;iif(l[i])}}
}return res;//返回自由變元數
}int b[maxn][maxn]=,,,
,,,,
,};int main()
res=solve(a,l,ans,n,m);
// for(int i=0;i
// if(l[i]&&(ans[i])%4!=0) cout<<'x'// cout ahu;
for(int i=0;iif(l[i]&&ans[i]%4!=0)}}
for(multiset
::iterator it=ahu.begin();it!=ahu.end();it++) cout
<<*(it)<<' ';
return
0;}
//下面是有區別的**部分
//gauss消元 行相消
for(int j=r+1;j//j是行數 從r+1開始 是上三角 不是對角 這樣要從下往上回代
if(a[j][i])
}l[i]=true,++r;
}//下面求結果 不考慮自由變元
for(int i=n-1;i>=0;--i)
}//列舉求值 因為題目要求最短的序列 即x盡量小 所以有滿足的直接break就行
//這裡可能出現多解的情況 一般情況是解同余式ax同餘c(mod m)
for(ans[i]=0;ans[i]if((ans[i]*a[i][i]+mod)%mod==temp) break;
}
Gauss 高斯消元
ans 直接用初中的解方程組的方法呀!沒錯,直接暴力加減消元。那什麼是 高斯消元 說白了,就是普通的加減消元罷了。本人再考場上打了乙個暴力解方程,大家都說要高斯消元,弄得我方極了,最後才發現我打的暴力就是高斯消元 選其中乙個方程 將其他方程的其中乙個元與選出的方程統一係數 將選出的方程與其他方程相減...
POJ1830 開關問題 Gauss消元
有n個相同的開關,每個開關都與某些開關有著聯絡,每當你開啟或者關閉某個開關的時候,其他的與此開關相關聯的開關也會相應地發生變化,即這些相聯絡的開關的狀態如果原來為開就變為關,如果為關就變為開。你的目標是經過若干次開關操作後使得最後n個開關達到乙個特定的狀態。對於任意乙個開關,最多只能進行一次開關操作...
POJ 1830 開關問題(Gauss 消元)
time limit 1000ms memory limit 30000k total submissions 7726 accepted 3032 description 有n個相同的開關,每個開關都與某些開關有著聯絡,每當你開啟或者關閉某個開關的時候,其他的與此開關相關聯的開關也會相應地發生變化...