考虑第一个整数是A,A [i]等于A的第i个数字(基于0的索引,从右到左),第二个整数是B,B [i]等于第i个数字B(基于0的索引,从右到左)。
A和B的幸运总和等于C,C [i] = max(A [i],B [i])。如果i大于或等于整数大小,则第i个数字等于0.
例如,
幸运总和47和729是
max(7,9)=9 max(4,2)=4 max(0,7)=7 answer = 749
同样,幸运总和W =(74,92,477)
max(4,2) = 4 max(7,9) = 9 Lucky sum of 74,92 = 94 Lucky sum of W=(Lucky sum of (94,477))
是
max(4,7)=7 max(9,7)=9 max(0,4)=4
所以w的幸运总和= 497。
任务: 我们得到一个数组W,包含n(1< = n< = 50)个整数。
我们必须找到W的一些非空子序列,以便该子序列中的整数幸运总和为幸运数字 (幸运数字是正整数,其十进制表示仅包含幸运数字4和7.例如,数字47,744,4是幸运的,5,17,467不是。)。
约束:0< W [i]< 1E9
示例:
动态编程可以解决这个问题吗?
如何在C ++中有效解决这个问题?
答案 0 :(得分:0)
因为答案的每一点都是独立的。因此,请单独更新它们,整个算法需要O(n*log10(w))
这是我刚写的代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXL 15
using namespace std;
int n;
int ans[MAXL];
int main(){
int i,j,w;
scanf("%d",&n);
memset(ans,0,sizeof(ans));
while (n--){
scanf("%d",&w);
i = 0;
while (w>0){
j = w % 10;
ans[i] = max(ans[i], j);
i++;
w /= 10;
}
}
bool flag = false;
for (i=MAXL-1;i>=0;i--){
if (ans[i] > 0) flag = true;
if (flag) printf("%d",ans[i]);
}
printf("\n");
return 0;
}
答案 1 :(得分:0)
这是我能想到的(尚未完成):
将 DP 与位掩码一起使用。我们现在用以下方式表示一个数字:每个位分为五种:
我们可以很容易地看到,只要有8或9位,它就永远不会被添加到有效的解决方案中。现在我们使用位掩码来表示数字,这需要5^8
。
因此,我们让f[i][s]
表示我们可以从first i numbers
中选择子集的总方式来计算出数字whose bit-mask is s
。
这是我刚才写的代码.....
还剩下三件事:
__int64
使用long long
或int
代替f[][]
。queue
来加速枚举,如果我们使用for (i = 0;i < MAXS;i++)
进行枚举,则存在很多不可能的状态(即f [] [s] == 0)。示例代码:
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 51
#define MAXS 390625 //5^8
using namespace std;
const int exp[] = {1, 5, 25, 125, 625, 3125, 15625, 78125, 390625};
int n;
int w[MAXN];
struct node{
int i;
int stat;
node(int x, int y):i(x),stat(y){}
};
queue<node> q;
__int64 f[MAXN][MAXS];
bool inq[MAXN][MAXS];
int main(){
//freopen("test.txt","r",stdin);
memset(f,0,sizeof(f));
memset(inq,0,sizeof(inq));
scanf("%d",&n);
for (int i = 0;i < n;i++) scanf("%d",&w[i]);
while (!q.empty()) q.pop();
f[0][0] = 1;
for (int i = 0;i < n;i++)
for (int j = 0;j < MAXS;j++)
if (f[i][j] > 0){
f[i + 1][j] += f[i][j];
int stat = j;
int loc = 0;
int k = 0;
for (int p = w[i];p > 0;p /= 10){
k = p % 10;
if (k <= 0) k = 0;
else if (k <= 3) k = 1;
else if (k <= 4) k = 2;
else if (k <= 6) k = 3;
else if (k <= 7) k = 4;
else k = -1;
if (k < 0) break;
int bit = stat % exp[loc + 1] / exp[loc];
if (k < bit) k = bit;
stat = stat - (bit - k) * exp[loc];
loc++;
}
if (k < 0) continue;
f[i + 1][stat] += f[i][j];
}
int ans = 0;
for (int i = 0;i < MAXS;i++){
bool flag = false;
for (int loc = 7;loc >= 0;loc--){
int bit = i % exp[loc + 1] / exp[loc];
if (bit > 0) flag = true;
if (flag == true && (bit != 2 && bit != 4)){
flag = false;
break;
}
}
if (flag == true) ans += f[n][i];
}
printf("%d\n",ans);
return 0;
}