这题我暂时只会搞一个超时版。
问题是让你求解一块矩形巧克力能不能分成给定的几种面积。
这是一道状压dp题,具体思路就是看横着切以及竖着切可不可行。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 16, maxl = 60; int n, x, y; int a[maxn], sum[maxn], vis[maxl][maxl][1 << 15], f[maxl][maxl][1 << 15]; int bitcount(int S) { return S == 0 ? 0 : bitcount(S / 2) + (S & 1); } int dp(int r, int c, int S) { if (vis[r][c][S]) return f[r][c][S]; vis[r][c][S] = 1; if (r > c) swap(r, c); if (bitcount(S) == 1) return r * c == sum[S]; for (int S0 = S; S0; S0 = (S0 - 1) & S) { for (int r0 = 1; r0 <= (r / 2); r0++) { if (sum[S0] == r0 * c && sum[S ^ S0] == (r - r0) * c && dp(r0, c, S0) && dp(r - r0, c, S ^ S0)) return f[r][c][S] = 1; if (sum[S ^ S0] == r0 * c && sum[S0] == (r - r0) * c && dp(r0, c, S ^ S0) && dp(r - r0, c, S0)) return f[r][c][S] = 1; } for (int c0 = 1; c0 <= (c / 2); c0++) { if (sum[S0] == c0 * r && sum[S ^ S0] == (c - c0) * r && dp(r, c0, S0) && dp(r, c - c0, S ^ S0)) return f[r][c][S] = 1; if (sum[S ^ S0] == c0 * r && sum[S0] == (c - c0) * r && dp(r, c0, S ^ S0) && dp(r, c - c0, S0)) return f[r][c][S] = 1; } } return f[r][c][S] = 0; } int main() { // freopen("uva4794.in","r",stdin); while (scanf("%d", &n) && n) { scanf("%d%d", &x, &y); for (int i = 0; i < n; i++) scanf("%d", &a[i]); int S; memset(vis, 0, sizeof vis); for (S = 0; S < (1 << n); S++) { sum[S] = 0; for (int i = 0; i < n; i++) if (S & (1 << i)) sum[S] += a[i]; } if (dp(x, y, (1 << n) - 1)) printf("Yes "); else printf("No "); } return 0; }
但是这样搞会TLE,就连空间也存不下,所以务必要降维。
怎么降维呢,先留个坑,要开始补补数学了。。
接下来要干的事情还有很多,要大致过一下图论(最短路,生成树,强连通,双连通,二分图……),KMP,字符串操作,再加上线段树和树状数组。
这两周可以说是总算实现了我曾几何时对高中阶段的学习作出的一点点念想了。
我曾经写过一篇文章,大体内容就是我处在极度颓废状态下的无病呻吟,我在那篇文章中提到,何时才能找到自己的明灯?
现在开来,这盏明灯总算是出现在我眼前了,它可能很远,可能也只是视野范围内一小点跳动的光线,可它终究会出现,不过来的有点略迟了。
现在的状态简直不能再好,保证睡眠,每天长跑,作业迅速做完,还有时间写写归纳,晚自习还能跑来机房写个一两题,如果早点意识到这一点,并且从高一开始做起,现在的我,在看到眼前屏幕上跳跃的光标,又会作何感想呢?
往事不可追忆,历史无法挽回,我接下来能做的,就是尽力地保持,保持,再保持!
我想我绝不会让我高中三年就这么辜负,不会到了高中临近毕业时,再想起我今天写下的文章,心中只留下对当初的悔恨和对未来的渺茫。