uva11125 - Arrange Some Marbles 记忆化搜索

Problem H
Arrange Some Marbles
Input:
Standard Input

Output: Standard Output

 

you are given some marbles of n different color. You have to arrange these marbles in a line. The marbles adjacent with same color form a group. In each group there can be 1 to 3 marble. Adjacent group should have different color and size. The first and last group also should have different color and size. You are given the number of each of these n marbles. You have count the number of ways you can arrange them in a line maintaining the above constraints. For example you have 4 red marbles and 4 green marbles. You can arrange them in the following 8 way  - GGGRRGRR, GGRGGRRR, GGRRRGGR, GRRGGGRR, RGGRRRGG, RRGGGRRG, RRGRRGGG, RRRGGRGG.

 

Input

Input contains multiple number of test cases. The first line contain the number of test cases t (t<3000). Each of the next line contains one test case. Each test case starts with n (1 ≤ n ≤ 4) the number of different color. Next contains n integers. The i'th integer denotes the number of marble of color i. The number of marbles of any color is within the range 0..7 (inclusive). The color of the marbles are numbered from 1 to n.

 

Output

For each test case output contains one integer in one line denoting the number of ways you can arrange the marbles.

 

Sample Input                          Output for Sample Input

6

2 3 3

2 4 4

2 6 6

3 3 4 5

3 4 5 6

4 2 3 4 5

 

0

8

12

174

1234

1440

 


  意思是给你几种颜色的石头,每种颜色有一定的个数。排成一列,连续的必须是1-3个算一组,相邻的组连续的颜色和个数不能相同,同时最后一组和第一组颜色和个数不能相同。

  题目给的颜色最多4种,每种最多7个。数很小,所以可以用一个8进制的数来表示某一种状态。可以开一个5维的数组,前2维是第一组的颜色和个数,3,4维是这一组的颜色和个数,最后一维是剩下的石头状态(包括颜色和个数,用8进制的数表示)。用a[i]表示第i种颜色的个数,枚举第一组的情况,进行记忆化搜索。

  搜索的时候3个参数就行了,当前的组的颜色和个数,剩下的石头的个数,再对下一组枚举,保证和这一组颜色和个数不一样就行了。

  判断是否算过这个状态要把那个8进制的数算出来进行判断。

  如果剩下0个,也就是最后一组了,这时要判断和第一组是否矛盾。

  其实记录数组也可以不开5维,开3维,不记录第一组的颜色和状态,但是这样算每一组数据都要重新初始化一次。


#include<cstring>
#include<cstdio>
#include<iostream>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
int N;
int dp[10][10][10][10][4500],a[10];
int fc,fn;
int DP(int x,int y,int t){
    int i,j,s=0;
    if(!t){
        if(fc==x||fn==y) return 0; //和初始状态矛盾
        return 1;
    }
    for(i=0;i<4;i++) s=s*8+a[i];  //此时剩余石头的状态
    int &ans=dp[fc][fn][x][y][s];
    if(ans!=-1) return ans;
    ans=0;
    for(i=0;i<N;i++)
    for(j=1;j<=3&&j<=a[i];j++){
        if(i==x||j==y) continue; //和这一组矛盾的不能选
        a[i]-=j;
        ans+=DP(i,j,t-j);
        a[i]+=j;
    }
    return ans;
}
int main(){
     freopen("in.txt","r",stdin);
     int T;
     scanf("%d",&T);
     memset(dp,-1,sizeof(dp));
     while(T--){
        scanf("%d",&N);
        int i,j,s=0,ans=0;
        memset(a,0,sizeof(a));
        for(i=0;i<N;i++){
            scanf("%d",&a[i]);
            s+=a[i];
        }
        if(!s) ans=1;
        for(i=0;i<N;i++)
        for(j=1;j<=3&&j<=a[i];j++){ //枚举第一组
            fc=i;
            fn=j;
            a[i]-=j;
            ans+=DP(i,j,s-j);
            a[i]+=j;
        }
        printf("%d\n",ans);
     }
     return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值