IDTitleSolvedSource
  2396 Budget 285 Tehran 2003 Preliminary
2397 Spiderman 307 Tehran 2003 Preliminary
2398 Toy Storage 405 Tehran 2003 Preliminary
  2399 A Mayor Problem 25 Tehran 2003 Preliminary
  2400 Supervisor, Supervisee 151 Tehran 2003 Preliminary
  2401 Street Polygon 12 Tehran 2003 Preliminary
2402 Palindrome Numbers 830 Tehran 2003 Preliminary

    (边做边更新~)

    Spiderman:

    蜘蛛男可以爬上爬下,给定一定距离,或上或下,最终到达原地点。

    一开始维护一个优先队列,很明显的超时了,于是乎往DP方面想,发现所有点的和最大为1000,则可以设计一个 DP[ 第几个点 ][ 此时的高度 ],那么DP[N][0]则为最小楼高,状态转移为(具体看代码):

    1、往上爬,若最优值大于此时该点的值,那么不用变化值,反之,最有值为该点高度值

    2、往下爬,最优值不变

    最后回朔一遍,输出上上下下就好了。

代码
1 #include <cstdio>
2
3  using namespace std;
4
5  const int maxn = 1004;
6 const int inf = 199999999;
7
8 int n, a[maxn], dp[maxn][maxn];
9
10 struct node { int x, y; char c; } f[maxn][maxn];
11
12 void print(int x, int y)
13 {
14 if(f[x][y].x == -1)
15 return ;
16 print(f[x][y].x , f[x][y].y);
17 printf("%c", f[x][y].c);
18 }
19
20 void solve()
21 {
22 for(int i=1; i <= n; i++) {
23 for(int j=0; j < maxn; j++) {
24 dp[i][j] = inf;
25 f[0][j].x = -1;
26 }
27 }
28
29 dp[1][ a[1] ] = a[1];
30 f[1][ a[1] ].x = 0;
31 f[1][ a[1] ].y = 0;
32 f[1][ a[1] ].c = 'U';
33
34 for(int i=2; i <= n; i++) {
35 for(int j=0; j < maxn; j++) {
36
37 if(j - a[i] >= 0 && dp[i][j] >= dp[i - 1][j - a[i]])
38 {
39 if(dp[i - 1][j - a[i]] >= j)
40 dp[i][j] = dp[i - 1][j - a[i]];
41 else
42 dp[i][j] = j;
43 f[i][j].x = i - 1;
44 f[i][j].y = j - a[i];
45 f[i][j].c = 'U';
46 }
47
48 if(j - a[i] >= 0 && dp[i][j - a[i]] >= dp[i - 1][j])
49 {
50 dp[i][j - a[i]] = dp[i - 1][j];
51 f[i][j - a[i]].x = i - 1;
52 f[i][j - a[i]].y = j;
53 f[i][j - a[i]].c = 'D';
54 }
55
56 }
57 }
58 if(dp[n][0] == inf)
59 printf("IMPOSSIBLE");
60 else
61 print(n , 0);
62 puts("");
63 }
64
65 int main()
66 {
67 int cas;
68 scanf("%d", &cas);
69 while(cas --)
70 {
71 scanf("%d", &n);
72 for(int i=1; i <= n; i++)
73 scanf("%d", &a[i]);
74 solve();
75 }
76 return 0;
77 }
78

    Toy Storage:

    用n个板子把一个箱子分成n + 1块,然后丢进去m个玩具,最后统计t (t > 0)的格子有多少个。

    先给线段从左到右排序,然后每次迭代,若点在该直线的左边,则这个点落在距离这条直线左边最近格子上,否则迭代到下一条直线

代码
1 #include <cstdio>
2 #include <algorithm>
3
4  using namespace std;
5
6  const double inf = 1999999999;
7  const int maxn = 1005;
8
9 struct line { double k, b; } L[maxn]; //直线方程 y = kx + b
10 struct node { double x, y; } a[maxn];
11
12 int n, m, toy[maxn], ans[maxn];
13 double x1, y1, x2, y2;
14
15 bool cmp(const node A, const node B)
16 {
17 return A.x < B.x;
18 }
19
20 line get(double x, double y)
21 {
22 line tmp;
23 double k , b;
24 if(x == y) {
25 k = inf;
26 b = x;
27 }
28 else {
29 k = (y2 - y1) / (y - x);
30 b = y1 - x * k;
31 }
32 tmp.k = k;
33 tmp.b = b;
34 return tmp;
35 }
36
37 bool check(double x, double y, line ll)
38 {
39 if(ll.k == inf) {
40 if(x <= ll.b)
41 return true;
42 return false;
43 } else {
44 double Y = ll.k * x + ll.b;
45 if(ll.k > 0 && Y <= y)
46 return true;
47 else if(ll.k < 0 && Y >= y)
48 return true;
49 else
50 return false;
51 }
52 }
53
54 void solve()
55 {
56 double x, y;
57 for(int i=0; i < m; i++)
58 {
59 scanf("%lf %lf", &x, &y);
60 bool flag = false;
61 for(int j=0; j < n; j++)
62 {
63 if(check(x , y, L[j]))
64 {
65 flag = true;
66 toy[j] ++;
67 break;
68 }
69 }
70 if(!flag) toy[n] ++;
71 }
72 for(int i=0; i <= n; i++)
73 ans[ toy[i] ] ++;
74 puts("Box");
75 for(int i=1; i <= m; i++)
76 if(ans[i] != 0)
77 printf("%d: %d\n", i , ans[i]);
78 }
79
80 int main()
81 {
82 while(~scanf("%d", &n), n)
83 {
84 memset(toy, 0, sizeof(toy));
85 memset(ans, 0, sizeof(ans));
86
87 scanf("%d %lf %lf %lf %lf", &m, &x1, &y1, &x2, &y2);
88 for(int i=0; i < n; i++)
89 scanf("%lf %lf", &a[i].x, &a[i].y);
90
91 sort(a, a + n, cmp);
92 for(int i=0; i < n; i++)
93 L[i] = get(a[i].x , a[i].y);
94
95 solve();
96 }
97 return 0;
98 }

    Palindrome Numbers:

    有这个规律: 1位数 : 9个回文 2位数 : 9个回文 3位数 : 90个回文 4位数 : 90个回文 ...

    既首尾有9种选择,而中间有10种选择。又前后需要一致,所以统计的时候只需要统计前(n + 1) / 2项即可

代码
1 #include <cstdio>
2 using namespace std;
3
4 typedef __int64 LL;
5
6 const int maxn = 10000;
7 const LL inf = 1000000000 * 2;
8
9 int LEN;
10 LL sum[maxn], a[maxn], digit[maxn], n, tmp;
11
12 void init()
13 {
14 LL i;
15 sum[1] = 9 , sum[2] = 18;
16 a[1] = 9 , a[2] = 9;
17 for(i=3; ; i += 2)
18 {
19 a[i] = a[i - 1] * 10;
20 sum[i] = sum[i - 1] + a[i];
21
22 a[i + 1] = a[i];
23 sum[i + 1] = sum[i] + a[i + 1];
24
25 if(sum[i + 1] >= inf)
26 break;
27 }
28 LEN = i + 1;
29 }
30
31 int main()
32 {
33 init();
34 while(~scanf("%I64d", &n) , n)
35 {
36 int i;
37 for(i=1; i <= LEN; i++)
38 {
39 if(sum[i] >= n) {
40 n -= sum[i - 1];
41 break;
42 }
43 }
44 LL tmp = 1;
45 for(int j=2; j <= ((i + 1) >> 1); j++)
46 tmp *= 10;
47 tmp += n - 1;
48
49 printf("%I64d", tmp);
50
51 if(i & 1)
52 tmp /= 10;
53 while(tmp) {
54 int t = tmp % 10;
55 printf("%d", t);
56 tmp /= 10;
57 }
58 puts("");
59 }
60 return 0;
61 }

 

 

   

posted on 2010-05-24 14:25  xIao.wU 思维磁场  阅读(353)  评论(0编辑  收藏  举报