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