您的位置:首页 > 其它

UVa 10400 - Game Show Math

2013-08-24 16:12 441 查看
  题目大意:给出n(n<100)个正整数和一个目标数,按照给出数的顺序,运用+、-、*、/四则运算(不考虑优先级),判断能否得出所要的结果。

  首先考虑的就是暴力枚举,不过时间复杂度为O(4n),会超时。由于题目限定中间运算结果在[-32000, 32000]内,当n到一定程度后(4n远远大于64000后),就会存在大量的重复子问题,可以通过记忆化搜索的方法去重,具体到这个问题就是vis数组的运用。

#include <cstdio>
#include <cstring>
#define MAXN 100+10

long long a[MAXN], target;
char op[MAXN];
int n;
bool ok, vis[MAXN][32000*2+100];

bool judge(int cur, int n)
{
return n >= -32000 && n <= 32000 && !vis[cur][n+32000];
}

void dfs(int cur, long long res)
{
if (cur == n )
{
if (res == target)  ok = true;
return;
}
if (!ok && judge(cur, res+a[cur]))
{
op[cur] = '+';
vis[cur][res+a[cur]+32000] = true;
dfs(cur+1, res+a[cur]);
}
if (!ok && judge(cur, res-a[cur]))
{
op[cur] = '-';
vis[cur][res-a[cur]+32000] = true;
dfs(cur+1, res-a[cur]);
}
if (!ok && judge(cur, res*a[cur]))
{
op[cur] = '*';
vis[cur][res*a[cur]+32000] = true;
dfs(cur+1, res*a[cur]);
}
if (!ok && res % a[cur] == 0 && judge(cur, res/a[cur]))
{
op[cur] = '/';
vis[cur][res/a[cur]+32000] = true;
dfs(cur+1, res/a[cur]);
}
}

int main()
{
#ifdef LOCAL
freopen("in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%lld", &a[i]);
scanf("%lld", &target);
ok = false;
memset(vis, 0, sizeof(vis));
vis[0][a[0]+32000] = true;
dfs(1, a[0]);
if (ok)
{
for (int i = 0; i < n-1; i++)
printf("%lld%c", a[i], op[i+1]);
printf("%lld=%lld\n", a[n-1], target);
}
else  printf("NO EXPRESSION\n");
}
return 0;
}


View Code
  也可以用递推的方法求解,不过在打印结果的时候要麻烦一些,二者的思想是一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: