hdu6407(恶心状压dp)

这个题可以说是十分十分恶心的题了。。

状态还是很容易想出来的,设d[i][S]为处理到i行时各列的状态,其中0表示该列没有气球,1表示该列已经被炸过,2表示该列有气球还没被炸掉,然后发现行比列小所以把行列转置一下就能降低复杂度。。。

然后分该行有没有选择气球炸掉和选哪个炸掉去转移就可以了。。

复杂度是O(n*m*3^m)。。emmmm为什么没有k。。因为S就表明了炸了几次(列),已经包含了k。。

然后实现才是最恶心的。。。

一方面是三进制比较难写。。想着用4进制表示能用位运算加速。。结果发现dp滚动数组的申请已经就把内存刚好用光了,必须写三进制(被出题人安排得明明白白

另一方面是答案会爆longlong,要写小高精。。(取个模会死嘛qaq

然后是滚动数组不能赋值,必须边转移边清空,即用01滚动数组。。以后写滚动都用这个了。。

总之写得很吐血,跑起来也很慢。。这1e10的复杂度算出来估计窝当场都不敢写。。

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 25
#define nm 540005 
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=1e12;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}



int n,m,_p,p3[NM],p[NM],num[nm],b[NM],c[nm][13],tot,_t;
bool _v[nm],a[NM][NM];
char _s[NM];
ll d[2][nm],ans[NM];


int main(){
    //freopen("data.in","r",stdin);
    p3[0]=p[0]=1;
    inc(i,1,12)p3[i]=p3[i-1]*3;
    inc(i,1,20)p[i]=p[i-1]*i;
    n=p3[12]-1;
    inc(i,0,n){
	_v[i]=true;
	for(int x=i,j=1;x;j++,x/=3)c[i][j]=x%3;
	inc(j,1,12)num[i]+=c[i][j]==1,_v[i]=_v[i]&&c[i][j]<=1;
    }
    int _=read();while(_--){
	mem(d);mem(ans);mem(b);
	m=read();n=read();_p=read();
	inc(j,1,m){
	    scanf("%s",_s+1);
	    inc(i,1,n)a[i][j]=_s[i]=='Q';
	}
	inc(i,1,n){
	    dec(j,m,1)b[i]*=3,b[i]+=a[i][j]?2:0;
	}
	tot=p3[m]-1;d[_t=0][0]=1;
	inc(i,1,n){
	    _t^=1;
	    inc(j,0,tot)if(d[_t^1][j]&&num[j]<=_p){
		int t=0;
		dec(k,m,1)if(c[j][k]==1)t=t*3+1;else t=t*3+(c[j][k]||c[b[i]][k]?2:0);
		d[_t][t]+=d[_t^1][j];
		if(num[j]<_p)inc(k,1,m)if(a[i][k]&&c[j][k]!=1){
		    t=j+(1-c[j][k])*p3[k-1];
		    d[_t][t]+=d[_t^1][j];
		}
		d[_t^1][j]=0;
	    }
	    //inc(j,0,tot)printf("%d ",f[j]);putchar('\n');
	}
	inc(j,0,tot)if(d[_t][j]&&_v[j])ans[num[j]]+=d[_t][j];
	inc(i,1,_p){
	    __int128 t=ans[i];t*=p[i];
	    if(t>inf)printf("%lld%012lld\n",(ll)(t/inf),(ll)(t%inf));
	    else printf("%lld\n",(ll)t);
	}
    }
    return 0;
}

Pop the Balloons

Time Limit: 7000/7000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 180    Accepted Submission(s): 63


 

Problem Description

Recently, an interesting balloon-popping game can be commonly found near the streets. The rule of this game is quite simple: some balloons are tied to cells of an n×m lattice, and you are allowed to throw k darts to prick the balloons. The more balloons you pierce, the more incredible prize you will get.

Probably because too many people have got bored with this childish game, a new variation of the game has appeared. In this variation, the balloons are replaced with more powerful ones: when a balloon explodes, strong gusts travel in four directions, blowing away all remaining balloons in the same row and column. In order to reduce the difficulty, not all cells are filled with a balloon.

For example, if you prick the yellow balloon in the following figure, then the red balloons will be blown away, with only the blue balloon remaining.
 



Now, you are given k darts. Since you are a good dart player that you can precisely throw it to any position you want, it is easy for you to use these k darts to clear all balloons (either by directly pricking, or by blowing away by other exploded balloons). Now you begin to consider: for every 1≤xk, how many different ways are there to clear all balloons with exactly x darts? Two ways are considered different if and only if there exists i, such that the positions of i-th pricked balloons differ. Note that you cannot throw the dart to an empty cell.  

Input

The first line of input is a single integer T (1≤T≤100), denoting the number of test cases.

Each test case begins with a line of three integers m,n (1≤m≤12,1≤n≤20), denoting the size of the balloon lattice, and k (1≤k≤20), denoting the number of darts. The next m lines, each containing n characters, describe the balloon lattice. Each character is either '

猜你喜欢

转载自blog.csdn.net/qkoqhh/article/details/81747553