Numbers Game
/*
题意:给你N(4-7)个数,这些数可以用也可以不用,将用的数通过+,-,*,/,()计算出一个最接近V的数。
思想:假设有 数字a,b,c,d(这里我没有考虑不连续的情况,如出现:a,b,d,不知道为什么也ac了,代码仅供参考···)(这里我用@代替四则运算解释)
那么我们先计算出长度为2的可能出现的组合 a@b,b@c,c@d;
长度为3的可能出现的组合 (a@b)@c,a@(b@c),(b@c)@d,b@(c@d);
长度为4的可能出现的组合 a@(b@c)@d),a@(b@(c@d)),(a@b)@(c@d),((a@b)@c)@d,(a@(b@c))@d
所以状态方程可以是 dp[j][k]=dp[j][c]@dp[c+1][k];
*/
#include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; __int64 dp[8][8][50000]; int bj[8][8]; void FC(int j,int k,int c,int c1) { int h,l;__int64 cs=(__int64)1<<60; for(h=0;h<bj[j][c];h++) for(l=0;l<bj[c1][k];l++) { dp[j][k][bj[j][k]++]=dp[j][c][h]+dp[c1][k][l]; dp[j][k][bj[j][k]++]=dp[j][c][h]-dp[c1][k][l]; if(dp[j][c][h]==0||abs(cs/dp[j][c][h])>abs(dp[c1][k][l]))dp[j][k][bj[j][k]++]=dp[j][c][h]*dp[c1][k][l]; if(dp[c1][k][l]!=0) dp[j][k][bj[j][k]++]=dp[j][c][h]/dp[c1][k][l]; } } int main() { int v,n; int i,j,k,c,t=0; int len; while(1) { scanf("%d %d",&v,&n); if(v==0&&n==0) break; memset(bj,0,sizeof(bj)); for(i=1;i<=n;i++) { scanf("%I64d",&dp[i][i][0]); bj[i][i]=1; } for(i=1;i<=(n-1);i++) for(j=1;(j+i)<=n;j++) { k=i+j; for(c=j;c<k;c++) FC(j,k,c,c+1); sort(dp[j][k],dp[j][k]+bj[j][k]); len=0;t=0; dp[j][k][len++]=dp[j][k][0]; for(t=1;t<bj[j][k];t++) if(dp[j][k][t]!=dp[j][k][t-1]) dp[j][k][len++]=dp[j][k][t]; bj[j][k]=len; } __int64 max=(__int64)1<<60; for(i=1;i<=n;i++) for(j=i;j<=n;j++) for(k=0;k<bj[i][j];k++) { if(abs(dp[i][j][k]-v)<abs(max-v)) max=dp[i][j][k]; } printf("%I64d\n",max); } return 0; }