您的位置:首页 > 其它

URAL 1658 Sum of Digits (DP) #by Plato

2013-03-18 23:58 429 查看


URAL 1658 Sum of Digits (DP) #by Plato

http://acm.timus.ru/problem.aspx?space=1&num=1658

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=20662#problem/B

题意: 已知一个长度<= 100的数,每位之和为s1,每位的平方和 为 s2,求这个数(多个答案输出最小的)

解法: f[i][j] 代表 每位和为i,平方和为j的最短长度。

f[i][j] = min{f[i – k][j – k*k]}

还算简单的DP吧,但是自己在其他地方犯了些错,当时就没有好的想法。

1. 第一次审题失误,看题时s1,s2 <= 10000,然后就觉得数据的范围是10^8,尝试了却也无从下手。

事实上,数据有效范围是:900*8100,这个复杂度在时间和空间上就都可以接受了。

2. 然后DP方程确定了,开始去写。WA了几次:判定“No solution”的条件没写全,

漏了f[s1][s2] > 100,还漏了 s1,s2超出有效范围的判定。

3. TLE,这也不得不说是个失误。

开始的时候,是每个case都DP一次,范围是s1,s2,两个错误:s1,s2在有效范围的DP才有用;直接在900*8100范围DP只需要一次就OK了。

不知道怎么得脑袋没转过来,两个问题查了有这么就都一直没有发现,后面对比别人的代码才发现,发现自己的代码小数据比它快很多,大数据却又慢很多。

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#define OP(s) cout<<#s<<"="<<s<<" ";
#define TP(i,j,k) cout<<#i<<"="<<i<<" "<<#j<<"="<<j<<" "<<#k<<"="<<k<<endl;
#define PP(s) cout<<#s<<"="<<s<<endl;
using namespace std;
int ans[200];
int choice[910][8110];

void find(int s1,int s2,int index)
{
if (!index) return;
int tmp = choice[s1][s2];
ans[index] = tmp;
find(s1 - tmp,s2 - tmp*tmp,--index);
}

int main()
{
freopen("test.txt","r",stdin);
int dig2[10];
for (int i = 0; i < 10; i++) dig2[i] = i*i;

static int f[910][8110];
for (int i = 0;i < 910;i++) for (int j = 0;j < 8110;j++) f[i][j] = 1<<29;
f[0][0] = 0;
for (int i = 1; i <= 900; i++)
for (int j = 1; j <= 8100; j++)
{
for (int k = 1; k <= 9; k++)
{
//if (i < k || j < dig2[k]) break;
int tmp;
//int tmp = f[i-k][j - dig2[k]] +1;
//if (tmp > 100) continue;
if (i >= k && j >= dig2[k] && (tmp = f[i-k][j - dig2[k]] +1) < f[i][j])
{
f[i][j] = tmp;
choice[i][j] = k;
}

}
}

int T;
scanf("%d",&T);
while(T--)
{
int s1,s2;
scanf("%d%d",&s1,&s2);

int sa;
if (s1 > 900 || s2 > 8100 || (sa = f[s1][s2]) > 100)
{
printf("No solution\n");
continue;
}

find(s1,s2,sa);
sort(ans+1,ans+sa+1);
for (int i = 1; i <= sa; i++) printf("%d",ans[i]);
printf("\n");
}

return 0;
}
/*
1. 第一次审题失误,看题时s1,s2 <= 10000,然后就觉得数据的范围是10^8,尝试了却也无从下手。
事实上,数据有效范围是:900*8100,这个复杂度在时间和空间上就都可以接受了。
2. 然后DP方程确定了,开始去写。WA了几次:判定“No solution”的条件没写全,
漏了f[s1][s2] > 100,还漏了 s1,s2超出有效范围的判定。
3. TLE,这也不得不说是个失误。
开始的时候,是每个case都DP一次,范围是s1,s2,两个错误:s1,s2在有效范围的DP才有用;直接在900*8100范围DP只需要一次就OK了。
不知道怎么得脑袋没转过来,两个问题查了有这么就都一直没有发现,后面对比别人的代码才发现,发现自己的代码小数据比它快很多,大数据却又慢很多。
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: