糯米

TI DaVinci, gstreamer, ffmpeg
随笔 - 167, 文章 - 0, 评论 - 47, 引用 - 0
数据加载中……

POJ 2430 Lazy Cows 动态规划

属于状态型的动态规划,特难搞的那一类,状态一多,转换的时候难免遗漏一两个。
这题还算,借助数据搞出来了,漏了两个转移,结果一组数据过不了。
后来加上就AC了,时间还行,32MS。

思路:
从左往右开始放矩形,假设现在准备摆放第i列之后的矩形。
实际上我们只关注第i-1列是怎么摆的,前面怎么摆都无所谓。
所以,
第i列牛的状态 + 第i-1列摆放的状态 -> 第i列摆放的状态
摆放的状态有五种:
1. 光上面有
2. 光下面有
3. 上下都有但不属于同一个矩形
4. 空
5. 上下都有并且属于同一个矩形
牛的状态有四种,就是1~4。

然后就看怎么推了,详见代码。
代码中对状态的定义也是按照上面的顺序。

在网上找解题报告,发现有的大牛代码很短很快很牛逼!佩服!

ps:
一开始这份代码用g++和gcc提交是WA的,但c++提交可以AC。
我在本地测试了一下,发现g++和gcc编译后,数据是跑得过的。我的gcc版本很高,是4.3.3。
不知道是北大的网站有问题,还是我的代码有问题。不过后者可能性大很多。
后来,我把inline去掉(#define inline),再用g++、gcc提交,就过了!
很想不通,写其他代码的时候,也是gcc编译的,不都是这样写 inline 的吗,也没见出什么问题,也不可能出问题。
所以希望高手给指点一下!谢谢!


代码:

#include <stdio.h>
#include 
<stdlib.h>

enum {
    UP, DOWN, UPDOWN, SPACE, CONN
}
;

#define MAX_N 1024
#define MAX_AREA (15000000 * 2)

#define inline

struct cow_node {
    
int y, x;
}
;
int dp[2][5][MAX_N], (*cur)[MAX_N], (*pre)[MAX_N];
struct cow_node cows[MAX_N];
int N, K, B, max_k;

int cmp(const void *a, const void *b)
{
    
return ((struct cow_node *)a)->- ((struct cow_node *)b)->x;
}


inline 
int min(int a, int b)
{
    
return a < b ? a : b;
}


inline 
void swap(void *a, void *b)
{
    
void *= *(void **)a;
    
*(void **)a = *(void **)b;
    
*(void **)b = t;
}


inline 
void init(int (*t)[MAX_N])
{
    
int i;

    
for (i = 0; i <= max_k + 4; i++
        t[
0][i] = t[1][i] = t[2][i] = t[3][i] = t[4][i] = MAX_AREA;
}


#if 0
inline 
void dump(int (*t)[MAX_N], int ptn)
{
#define dbp printf
    
int i, j;
    
const char *strs[] = {
        
"up""down""updown""space""conn"
    }
;
    
const char *ptns[] = {
        
"*\n\n""\n*\n""*\n*\n""\n\n" 
    }
;

    dbp(
"---------\n%s", ptns[ptn]);
    
for (i = 0; i < 5; i++{
        dbp(
"%s: ", strs[i]);
        
for (j = 0; j <= max_k; j++)
            dbp(
"%d->%d ", j, t[i][j]);
        dbp(
"\n");
    }

    dbp(
"\n");
#undef dbp
}

#else
#define dump() {}
#endif

inline 
void calc(int ptn, int space_cnt)
{
    
int i;

#define UPDATE(_from, _to, _a_used, _k_used) \
    cur[_to][i 
+ _k_used] = min(cur[_to][i + _k_used], pre[_from][i] + _a_used)
    
#define CASE(_ptn, _code) \
    
if (ptn == _ptn) {    \
        
for (i = 0; i <= max_k; i++) \
            _code    \
    }

    
    init(cur);

    CASE(UP, 
{
        UPDATE(UP, UP, 
10);
        UPDATE(UPDOWN, UP, 
10);
        UPDATE(UPDOWN, UPDOWN, 
20);
        UPDATE(DOWN, UP, 
11);
        UPDATE(DOWN, UPDOWN, 
21);
        UPDATE(CONN, CONN, 
20);
        UPDATE(CONN, UP, 
11);
        UPDATE(SPACE, UP, 
11);
        UPDATE(SPACE, CONN, 
21);
    }
);

    CASE(DOWN, 
{
        UPDATE(DOWN, DOWN, 
10);
        UPDATE(UPDOWN, DOWN, 
10);
        UPDATE(UPDOWN, UPDOWN, 
20);
        UPDATE(UP, DOWN, 
11);
        UPDATE(UP, UPDOWN, 
21);
        UPDATE(CONN, CONN, 
20);
        UPDATE(CONN, DOWN, 
11);
        UPDATE(SPACE, DOWN, 
11);
        UPDATE(SPACE, CONN, 
21);
    }
);

    CASE(UPDOWN, 
{
        UPDATE(UP, UPDOWN, 
21);
        UPDATE(UPDOWN, UPDOWN, 
20);
        UPDATE(DOWN, UPDOWN, 
21);
        UPDATE(CONN, CONN, 
20);
        UPDATE(SPACE, CONN, 
21);
        UPDATE(SPACE, UPDOWN, 
22);
    }
);

    CASE(SPACE, 
{
        UPDATE(UP, SPACE, 
00);
        UPDATE(UP, UP, space_cnt, 
0);
        UPDATE(DOWN, SPACE, 
00);
        UPDATE(DOWN, DOWN, space_cnt, 
0);
        UPDATE(UPDOWN, SPACE, 
00);
        UPDATE(UPDOWN, UPDOWN, space_cnt
*20);
        UPDATE(UPDOWN, UP, space_cnt, 
0);
        UPDATE(UPDOWN, DOWN, space_cnt, 
0);
        UPDATE(CONN, SPACE, 
00);
        UPDATE(CONN, CONN, space_cnt
*20);
        UPDATE(SPACE, SPACE, 
00);
    }
);

#undef UPDATE
#undef CASE

    dump(cur, ptn);

    swap(
&cur, &pre);
}



int main()
{
    
int i;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d%d"&N, &K, &B);
    
for (i = 0; i < N; i++
        scanf(
"%d%d"&cows[i].y, &cows[i].x);
    qsort(cows, N, 
sizeof(cows[0]), cmp);

    cur 
= dp[0];
    pre 
= dp[1];
    max_k 
= 2;
    init(pre);
    pre[SPACE][
0= 0;
    
for (i = 0; i < N; ) {
        max_k 
= min(i + 2, K);
        
if (i && cows[i - 1].x + 1 != cows[i].x) 
            calc(SPACE, cows[i].x 
- cows[i - 1].x - 1);
        
if (i + 1 < N && cows[i + 1].x == cows[i].x) {
            calc(UPDOWN, 
0);
            i 
+= 2;
        }
 else {
            calc(cows[i].y 
== 1 ? UP : DOWN, 0);
            i
++;
        }

    }

    calc(SPACE, 
0);

    printf(
"%d\n", pre[SPACE][K]);

    
return 0;
}


posted on 2010-04-13 12:19 糯米 阅读(988) 评论(0)  编辑 收藏 引用 所属分类: POJ


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理