聽說正解是高斯消元吶,但是我不會~(>_<)~
看到大家都寫了搜尋。
一種實現很簡單的方法是列舉1~n的排列,判斷是否可行。我算了算時間複雜度(其實我不會算,就大概估計了一下),發現會超時。
由於不會算複雜度,我對於這樣的暴搜能過50表示驚訝⊙ o ⊙
如果按照豎式從右至左的順序搜,就可以邊搜邊判斷是否可行了。
我寫得很麻煩,討論了很多情況,但是很多複製貼上就可以了。
具體的:
用v[i]記錄i所代表的值,use[i]記錄是否有字母代表i這個數字。
搜尋的時候,傳入的引數有:當前到了哪一位,上一位是否進製。
然後搜到某一位的時候,判斷哪些數被確定了,我分了0個,1個,2個,3個的情況,分別處理
(如果有多個沒有確定,也只能列舉乙個,然後進入下乙個搜尋,因為可能會出現,加數與加數或和的這一位是同乙個字母的情況)
有乙個剪枝是,搜到第i位的時候,判斷一下第i位到第n位,有沒有出現衝突的情況(衝突,即三個數都確定了,但是相加什麼的並不符合條件)
還有比較神奇的優化,比如列舉的時候倒著列舉。
注意進製什麼的。
經過和zcx的討論後,我終於知道自己**為什麼這麼長了。
學習了正常的方法。
搜尋的時候,如果當前列有兩個數不確定,就跳過這一列(就不用那麼多分類討論了)。
#include#include#include
#include
#include
using
namespace
std;
int n,a[31],b[31],c[31],v[31
];int use[31
];inline
intread()
while(isdigit(ch))
return ans*f;
}int buf[5
];inline
void write(int
x)bool flag=0
;inline
void
init()
for(register int j=1;j<=n;++j)
for(register int j=1;j<=n;++j)
}void dfs(int now,int
in) //
當前到哪一位,進製
for(int i=now;i<=n;i++)
if(v[a[i]]>-1&&v[b[i]]>-1&&v[c[i]]>-1
)
if(v[a[now]]>-1&&v[b[now]]>-1&&v[c[now]]>-1
)
else
return
; }
if(v[a[now]]>-1&&v[b[now]]>-1&&v[c[now]]==-1
)
else
return
; }
if(v[a[now]]>-1&&v[b[now]]==-1&&v[c[now]]>-1
)
else
return
; }
if(v[b[now]]>-1&&v[a[now]]==-1&&v[c[now]]>-1
)
else
return
; }
if(v[a[now]]>-1&&v[b[now]]==-1&&v[c[now]]==-1
)
}if(v[a[now]]==-1&&v[b[now]]>-1&&v[c[now]]==-1
)
}if(v[a[now]]==-1&&v[b[now]]==-1&&v[c[now]]>-1
)
}if(v[a[now]]==-1&&v[b[now]]==-1&&v[c[now]]==-1
)
}}int
main()
dfs(
1,0);
for(register int i=0;ii)
return0;
}
題解 洛谷P1092 蟲食算
p1092 我太弱了,竟然打了乙個上午。一開始我竟然想從a到b列舉每一種排列最後檢查。很顯然這種方法效率特別低 o n 於是想到了由低位到高位,由兩個加數上的位到和上的位,逐個列舉數字。當然如果不剪枝的話就和第一種方法沒什麼區別 這個剪枝比較好想,在每列舉完一列時 或者該列上的數字已被列舉了 檢查上...
洛谷P1092 蟲食算
所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看乙個簡單的例子 其中 號代表被蟲子啃掉的數字。根據算式,我們很容易判斷 第一行的兩個數字分別是5和3,第二行的數字是5。現在,我們對問題做兩個限制 首先,我們只考慮加法的蟲食算。這裡的加法是n進製加法,算...
洛谷P1092 蟲食算
所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看乙個簡單的例子 其中 號代表被蟲子啃掉的數字。根據算式,我們很容易判斷 第一行的兩個數字分別是5和3,第二行的數字是5。現在,我們對問題做兩個限制 首先,我們只考慮加法的蟲食算。這裡的加法是n進製加法,算...