SRM 451 DIV 1 总结
250p:这次是有史以来做的最快的一次250p。。。看题花了两分钟,敲代码最多一分钟。。。太明显了题意~
500p:这题水了。。。每次都这样。。。很显然用DP来做,不过前面状态表示有问题了。。。搞了好久还是错的。。
题意:给你一系列点,每个点都有一个硬币,刚开始从点(0, 0)开始走,每次只能按照以下规律走,第一次从(x, y)走到(x+k1, y+1),第二次从当前点(x, y)走到(x+k2, y+2),要保证k1 < k2 < ... < kn,问最多能收集几个硬币
解题思路:用dp[i][j]表示到了当前i这个点收集到j个硬币的最小步数,最小步数表示y-1走到当前y最少需要的步数,注意而不是前一个点走到当前点的步数。
250p:
class MagicalSource { public: long long calculate(long long x) ; }; long long MagicalSource::calculate(long long x) { LL cur = 1; while(x >= cur*10+1) { cur = cur*10+1; } while(x%cur != 0) { cur /= 10; } return x/cur; }
500p:
class BaronsAndCoins { public: int getMaximum(vector <int> x, vector <int> y) ; }; struct PP { int x, y; bool operator < (const PP &a) const { return y < a.y; } }a[55]; int dp[55][55]; int cal(int n) { return n*(n+1)/2; } int max(int a, int b) { return a > b ? a : b; } int BaronsAndCoins::getMaximum(vector <int> xx, vector <int> yy) { int len = xx.size(); int i, j, k; for(i = 1;i <= len; i++) { a[i].x = xx[i-1]; a[i].y = yy[i-1]; } sort(a+1, a + len+1); memset(dp, -1, sizeof(dp)); dp[0][0] = 0; a[0].x = 0, a[0].y = 0; for(i = 0;i <= len; i++) { for(j = i+1;j <= len; j++) { if(a[j].y == a[i].y || a[j].x <= a[i].x) continue; for(k = 0;k <= len; k++) if(dp[i][k] != -1){ int dis = a[j].x - a[i].x; int step = a[j].y - a[i].y; int now = dp[i][k]*step + cal(step); if(now > dis) continue; int curk = step+dp[i][k]; while(now < dis) { now += step; curk++; } if(dp[j][k+1] == -1) dp[j][k+1] = curk; else if(dp[j][k+1] > curk) dp[j][k+1] = curk; } } } int ans = 0; for(i = 0;i <= len; i++) for(j = 0;j <= len; j++) if(dp[i][j] != -1) { ans = max(ans, j); } return ans; }