今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的,由于要考虑好多东西,而且昨晚2点睡的有点困,最后终于磨蹭出来了,第一次的代码搓没关系,自己写的才重要。然后果然不出我所料,调试到了晚上才A了(一个郁闷的错误)。。。A的感觉真的是爽呀,虽然搞了差不多一天。当然自己写了自己想的代码后也要把代码优化,不然队友看不懂自己代码就囧了。。。
插头DP,建议大家想学的好好看看陈丹琦的国家集训队论文,这是个优美的DP。
http://www.docin.com/p-46797997.html
- #include <stdio.h>
- #include <string.h>
-
- #define LL __int64
-
- const int mod = 10007;
-
-
- struct HASH{
- int head[mod+10], E, next[80000];
- LL val[80000], cnt[80000];
-
- void init() {
- memset(head, -1, sizeof(head));
- E = 0;
- }
-
- int findhash(LL x) {
- return (x%mod + mod)%mod;
- }
-
- void add(LL x, LL sum) {
- int u = findhash(x);
- for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {
- cnt[i] += sum;
- return ;
- }
- val[E] = x;
- cnt[E] = sum;
- next[E] = head[u];
- head[u] = E++;
- }
-
- }biao1, biao2;
-
- int c[22], n, m, d[22];
-
- void get(LL x) {
- for(int i = m+1;i >= 1; i--) {
- c[i] = x&7;
- x /= 8;
- }
- }
-
- LL getval() {
- LL ret = 0;
- for(int i = 1;i <= m+1; i++) {
- ret |= d[i];
- ret *= 8;
- }
- ret /= 8;
- return ret ;
- }
-
- void change() {
- int vis[22];
- memset(vis, 0, sizeof(vis));
- int num = 1;
- for(int i = 1;i <= m+1;i ++) {
- if(!d[i]) continue;
- if(!vis[d[i]]) {
- vis[d[i]] = num;
- d[i] = num++;
- }
- else {
- d[i] = vis[d[i]];
- }
- }
- }
-
- void fuzhi() {
- for(int i = 1;i <= m+1;i ++) d[i] = c[i];
- }
-
- char s[22][22];
-
- int main() {
- int i, j, k, l;
- while(scanf("%d%d", &n, &m) != -1) {
- for(i = 1;i <= n; i++)
- scanf("%s", s[i]+1);
- int tot = 0;
- for(i = 1;i <= n; i++)
- for(j = 1;j <= m; j++)
- if(s[i][j] == '.') tot++;
- if(tot%2==1 || tot < 4) {
- puts("0");
- continue;
- }
- int tox = -1, toy = -1;
- for(i = 1;i <= n; i++)
- for(j = 1;j <= m; j++) if(s[i][j] == '.') {
- tox = i;
- toy = j;
- }
- biao1.init();
- biao1.add(0, 1);
- LL ans = 0;
- for(i = 1;i <= n; i++){
- for(j = 0;j <= m; j++){
- biao2.init();
- for(l = 0;l < biao1.E; l++) {
- get(biao1.val[l]);
- if(j == m) {
- for(int ii = 2;ii <= m+1; ii++) d[ii] = c[ii-1];
- d[1] = 0;
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- continue;
- }
- if(c[j+1] && !c[j+2]) {
- if(s[i][j+1] != '.') continue;
- if(j+2 <= m) {
- fuzhi();
- d[j+1] = 0;d[j+2] = c[j+1];
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- if(i < n) {
- fuzhi();
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- }
- else if(!c[j+1] && c[j+2]) {
- if(s[i][j+1] != '.') continue;
- if(i < n) {
- fuzhi();
- d[j+1] = c[j+2]; d[j+2] = 0;
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- if(j+2 <= m) {
- fuzhi();
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- }
- else if(!c[j+1] && !c[j+2]) {
- if(s[i][j+1] != '.') {
- fuzhi();
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- continue;
- }
- if(j+2 <= m && i < n) {
- fuzhi();
- d[j+1] = d[j+2] = 13;
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- }
- else {
- if(c[j+2] == c[j+1]) {
- int tot = 0;
- for(int ii = 1;ii <= m+1; ii++) if(c[ii])
- tot++;
- if(tot == 2 && i == tox && j+1 == toy) ans += biao1.cnt[l];
- }
- else {
- if(s[i][j+1] != '.') continue;
- fuzhi();
- for(int ii = 1;ii <= m+1; ii++) if(ii != j+1 && ii != j+2 && d[ii] == d[j+1]) {
- d[ii] = d[j+2];
- break;
- }
- d[j+1] = d[j+2] = 0;
- change();
- LL now = getval();
- biao2.add(now, biao1.cnt[l]);
- }
- }
- }
- biao1 = biao2;
- }
- }
- printf("%I64d\n", ans);
- }
- return 0;
- }