poj 2718

xiaoxiao2021-02-28  18

题意:给出一些数

对这些数进行随意组合,每个数不能重复使用,形成两个数(不能有前导零)A,B。问A,B最小的差。

直接dfs,数据不大,最多10个数。但也不能太盲目,两个数的差要小,这两个数的位数就要接近才行。我们就可以缩小搜索深度。就要就能A了。

最求一下速度,我们可以剪枝,当搜索第二个数的时候,因为两个数,不可能有相同的数,所以,我们可以在第二个数的后面加零。

若大于,则相减就是能得到的最小值,若还比ans大,就减掉。

若小于,就在后面以为加个九,则相减就是能得到的最小值,若还比ans大,就减掉。

#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn = 15; const int inf = 1e9; int vis[maxn], num[maxn]; int nums[6] = {1, 10, 100, 1000, 10000, 100000}; int ans, val; int cnt = 0, cnta, cntb; void dfsB(int deep, int vals) { if(deep == cntb) { //printf("%d\n", ans); ans = min(ans, abs(vals - val)); return; } if(vals)//剪枝 { if(vals * nums[cntb - deep] < val) { if(abs(vals * nums[cntb - deep] + 9 * nums[cntb - deep - 1] - val) >= ans) return; } else { if(abs(vals * nums[cntb - deep] - val >= ans)) return; } } for(int i = 0; i < cnt; i++) { if((deep != 0 || num[i] != 0 || deep + 1== cntb) && !vis[i]) { vis[i] = 1; dfsB(deep + 1, vals * 10 + num[i]); vis[i] = 0; } } } void dfsA(int deep, int vals) { if(deep == cnta) { val = vals; dfsB(0, 0); return; } for(int i = 0; i < cnt; i++) { if((deep != 0 || num[i] != 0 || deep + 1== cnta) && !vis[i]) { vis[i] = 1; dfsA(deep + 1, vals * 10 + num[i]); vis[i] = 0; } } } int main() { int T; scanf("%d", &T); getchar(); for(int kase = 1; kase <= T; kase++) { ans = inf; memset(vis, 0, sizeof(vis)); cnt = 0; char ch; while(scanf("%c", &ch) && ch != '\n') { if(ch <= '9' && ch >= '0') { num[cnt++] = ch - '0'; } } cnta = cnt / 2;//缩小搜索深度。 cntb = cnt - cnta; //printf("%d %d\n", cnta, cntb); dfsA(0, 0); printf("%d\n", ans); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-450004.html

最新回复(0)