【HDU4001】
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4001
【思路】
DP。
按长和宽从小到大、d值从大道小排序。
dp[i] = max(block[i].c, dp[j]+block[i].c)。其中1<=j<i。
dp[j]+block[i].c表示当i可以叠加在j上面时的值。如果不可叠加就无需计算。
注意排序中的d值。
还需要注意dp数组用整型会溢出。
【代码】
#include <iostream> #include <algorithm> using namespace std; const int maxn = 1000; struct block { int a; int b; int c; int d; }b[maxn+5]; bool cmp(const block &a, const block &b) { if (a.a!=b.a) return a.a<b.a; else if (a.b!=b.b) return a.b<b.b; else return a.d>b.d; } inline __int64 max(__int64 a, __int64 b) { if (a>=b) return a; else return b; } __int64 dp[maxn+5]; int main() { int n; int i, j; while(scanf("%d", &n)!=EOF) { if (n==0) break; for (i=0; i<n; i++) { scanf("%d %d %d %d", &b[i].a, &b[i].b, &b[i].c, &b[i].d); if (b[i].a<b[i].b) { int t = b[i].a; b[i].a = b[i].b; b[i].b = t; } } sort(b, b+n, cmp); for (i=0; i<n; i++) dp[i] = b[i].c; for (i=0; i<n; i++) { for (j=0; j<i; j++) { if (b[i].d==0) { if (b[i].a>=b[j].a && b[i].b>=b[j].b) dp[i] = max(dp[i], dp[j]+b[i].c); } else if (b[i].d==1) { if ((b[i].a>=b[j].a && b[i].b>b[j].b) || (b[i].a>b[j].a && b[i].b>=b[j].b)) dp[i] = max(dp[i], dp[j]+b[i].c); } else { if (b[i].a>b[j].a && b[i].b>b[j].b) dp[i] = max(dp[i], dp[j]+b[i].c); } } } __int64 ans = -1; for (i=0; i<n; i++) { if (dp[i]>ans) ans = dp[i]; } printf("%I64d\n", ans); } return 0; }
【HDU4002】
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4002
【思路】
数学题。
化简式子结果为质数从小到大相乘直到刚好不大于所给的数时的数。
可以先把质数相乘结果保存起来,60以内的质数相乘即可达到100位以上。
对于给定的数字扫描找出所须答案。
【代码】
#include <iostream> #include <cstring> using namespace std; char num[54][120] = { "2", "6", "30", "210", "2310", "30030", "510510", "9699690", "223092870", "6469693230", "200560490130", "7420738134810", "304250263527210", "13082761331670030", "614889782588491410", "32589158477190044730", "1922760350154212639070", "117288381359406970983270", "7858321551080267055879090", "557940830126698960967415390", "40729680599249024150621323470", "3217644767340672907899084554130", "267064515689275851355624017992790", "23768741896345550770650537601358310", "2305567963945518424753102147331756070", "232862364358497360900063316880507363070", "23984823528925228172706521638692258396210", "2566376117594999414479597815340071648394470", "279734996817854936178276161872067809674997230", "31610054640417607788145206291543662493274686990", "4014476939333036189094441199026045136645885247730", "525896479052627740771371797072411912900610967452630", "72047817630210000485677936198920432067383702541010310", "10014646650599190067509233131649940057366334653200433090", "1492182350939279320058875736615841068547583863326864530410", "225319534991831177328890236228992001350685163362356544091910", "35375166993717494840635767087951744212057570647889977422429870", "5766152219975951659023630035336134306565384015606066319856068810", "962947420735983927056946215901134429196419130606213075415963491270", "166589903787325219380851695350896256250980509594874862046961683989710", "29819592777931214269172453467810429868925511217482600306406141434158090", "5397346292805549782720214077673687806275517530364350655459511599582614290", "1030893141925860008499560888835674370998623848299590975192766715520279329390", "198962376391690981640415251545285153602734402721821058212203976095413910572270", "39195588149163123383161804554421175259738677336198748467804183290796540382737190", "7799922041683461553249199106329813876687996789903550945093032474868511536164700810", "1645783550795210387735581011435590727981167322669649249414629852197255934130751870910", "367009731827331916465034565550136732339800312955331782619462457039988073311157667212930", "83311209124804345037562846379881038241134671040860314654617977748077292641632790457335110", "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", "4445236185272185438169240794291312557432222642727183809026451438704160103479600800432029464270", "1062411448280052319722448549835623701226301211611796930357321893850294264731624591303255041960530", "256041159035492609053110100510385311995538591998443060216114576417920917800321526504084465112487730", "64266330917908644872330635228106713310880186591609208114244758680898150367880703152525200743234420230" }; int ct[54] = {1,1,2,3,4,5,6,7,9,10,12,13,15,17,18,20,22,24,25,27,29,31,33,35,37,39,41,43,45,47, 49,51,53,56,58,60,62,64,66,69,71,73,76,78,80,82,85,87,89,92,94,97,99,101};//先把上面结果的长度存起来效率会有所提高 int main() { char str[500]; int t; int i; int x, y; scanf("%d", &t); while(t--) { scanf("%s", str); x = strlen(str); for (i=0; i<54; i++) { y = ct[i]; if (x<y) break; else if (x>y) continue; else if (strcmp(str, num[i])<0) break; } printf("%s\n", num[i-1]); } return 0; }
【HDU4004】
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4004
【思路】
二分。
上届为L,下界为相邻位置的距离的最大值。
注意要先排序。
【代码】
#include <iostream> #include <algorithm> using namespace std; const int maxn = 500000; int pt[maxn+5]; inline int solve(int mid, int l) { int i = 0; int ct = 0; int cur = 0; while(cur<l) { cur += mid; while(cur>=pt[i+1]) i++; cur = pt[i]; ct++; } return ct; } int main() { int l, n, m; int i; int left, right, mid, t; int ans; while(scanf("%d %d %d", &l, &n, &m)!=EOF) { for (i=1; i<=n; i++) scanf("%d", &pt[i]); pt[0] = 0; pt[n+1] = l; pt[n+2] = INT_MAX; sort(pt, pt+n+2); left = 0; for (i=1; i<=n+1; i++) { if (pt[i]-pt[i-1]>left) left = pt[i] - pt[i-1]; } right = l; ans = INT_MAX; while(left<=right) { mid = (left+right)/2; t = solve(mid, l); if (t<=m) { right = mid - 1; ans = mid; } else { left = mid + 1; } } printf("%d\n", ans); } return 0; }
【HDU4006】
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4006
【思路】
最小堆。
用最小堆维护最大的k个值。
插入时,如果堆个数未满k个,则直接插入;
如果已满,则如果该数比堆最小的数大,则替换并对堆进行维护,如果比最小的数还小,则无需插入。
【代码】
#include <iostream> #include <cstring> using namespace std; int minheap[100005], lenmin; void exchange(int &a, int &b) { int t=a; a = b; b = t; } void min_heap_insert(int v)//×îС¶ÑµÄ²åÈë { lenmin++; minheap[lenmin] = v; int i=lenmin; while(i>1 && minheap[i/2]>minheap[i]) { exchange(minheap[i/2], minheap[i]); i /= 2; } } void min_heapify(int i)//×îС¶ÑµÄά»¤ { int l = 2*i, r = 2*i+1, smallest; if (l<=lenmin && minheap[l]<minheap[i]) { smallest = l; } else { smallest = i; } if (r<=lenmin && minheap[r]<minheap[smallest]) { smallest = r; } if (smallest!=i) { exchange(minheap[i],minheap[smallest]); min_heapify(smallest); } } int main() { int n, k; int i; int x; char s[4]; while(scanf("%d %d", &n, &k)!=EOF) { lenmin = 0; for (i=0; i<n; i++) { scanf("%s", s); if (s[0]=='I') { scanf("%d", &x); if (lenmin<k) { min_heap_insert(x); } else { if (x>minheap[1]) { minheap[1] = x; min_heapify(1); } } } else { printf("%d\n", minheap[1]); } } } return 0; }
【HDU4007】
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4007
【思路】
坐标离散化。
由于点的规模只有1000个,而坐标范围太大,所以需要离散化点。
对于存在的xy坐标值保存起来。假如有ctx个x坐标,cty个y坐标。
如果(x,y)有点,则标为1,否则为0。然后用sum[x][y]数组保存该点到(0,0)点所成矩阵的点个数和。
然后枚举新的ctx*cty的矩阵。
对于矩阵中的每一个点,将其作为area的右下顶点,利用sum可以计算其再 r 的范围内的点个数。
记录其最大值即为答案。
【代码】
#include <iostream> #include <algorithm> #include <map> using namespace std; const int maxn = 1000; int sum[maxn+5][maxn+5]; int x[maxn+5], y[maxn+5]; int ctx, cty; struct point { int x; int y; }pt[maxn+5]; inline int max(int a, int b) { if (a>=b) return a; else return b; } int main() { map<int, int> px, py; int n, r; int i, j; point temp; while(scanf("%d %d", &n, &r)!=EOF) { for (i=0; i<n; i++) { scanf("%d %d", &pt[i].x, &pt[i].y); } for (i=0; i<n; i++) { x[i+1] = pt[i].x; y[i+1] = pt[i].y; } sort(x+1, x+n+1); sort(y+1, y+n+1); px.clear(); py.clear(); for (i=1,ctx=0; i<=n; i++) { if (px.find(x[i])==px.end()) { ctx++; px[x[i]] = ctx; x[ctx] = x[i]; } } for (i=1,cty=0; i<=n; i++) { if (py.find(y[i])==py.end()) { cty++; py[y[i]] = cty; y[cty] = y[i]; } } memset(sum, 0, sizeof(sum)); for (i=0; i<n; i++) { sum[px[pt[i].x]][py[pt[i].y]] = 1; } for (i=1; i<=ctx; i++) { for (j=1; j<=cty; j++) { sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]; } } int sx = 1; int sy = 1; int ans = 0; for (i=1; i<=ctx; i++) { while(x[sx]+r<x[i]) sx++; sy = 1; for (j=1; j<=cty; j++) { while(y[sy]+r<y[j]) sy++; ans = max(ans, sum[i][j]-sum[sx-1][j]-sum[i][sy-1]+sum[sx-1][sy-1]); } } printf("%d\n", ans); } return 0; }