SRM 449 div1 (practice)

65 篇文章 0 订阅
21 篇文章 0 订阅
250pt:
   暴力枚举所有的可能的情况就好了,求面积的时候我是用梯形的面积减去两个三角形的面积。。
550pt:
题意:给你一个蜂窝形状的特殊图形,有一些格子已经被占据了,问你将剩下的格子用1*2的砖块尽可能的铺满的总方案数,见下图。



此题想了半天,隐约感觉可以dp,但是无从D起,,,膜拜了下rng_58的超短代码(大部分人选择dfs转移),但是rng_58将图转换成网格后巧妙的使用逐格递推的方法,代码超短,简直就是高端洋气上档次啊,好想又好写,这种题我以前都是dfs写转移的,要,b半天才能写出来。。
 #include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
class HexagonalBattlefield{
    public :
int countArrangements(vector <int> X, vector <int> Y, int N) ;
};
int g[250][250];
long long  dp[2][1<<15];
const int mod =  2000000011;
void Add(long long &x,int y)
{
    x += y;
    if(x >= mod) x -= mod;
}
int dx[] = {1,0,-1,0,1,-1};
int dy[] = {0,1,0,-1,1,-1};
vector<pair<int,int> > p;
int HexagonalBattlefield::countArrangements(vector <int> X, vector <int> Y, int N)
{
    N --;
    for(int i = -N; i <= N; i++) {
        for(int j = -N; j <= N; j++) if(abs(i-j)  <= N ){//ddddd
    //    puts("ddd");
            int t = 0;
            for(int k = 0; k < X.size(); k++) {
                if(i == X[k] && j == Y[k]) {t=1;break;}
            }
            if(!t) p.push_back(make_pair(i,j));
        }
    }
  //  puts("dddd");
    int m = p.size();
    for(int i = 0; i < m; i++) {
        int x = p[i].first , y = p[i].second;
        for(int j = 0; j < 6; j++) {
            int tx = x + dx[j];
            int ty = y + dy[j];
            for(int k = 0; k < m; k++) if(tx == p[k].first && ty == p[k].second) {
                g[i][k] = true;
            }
        }   
    }
  //  printf("m=%d\n",m);
   // puts("debug"); 
    int cur = 0, nxt = 1;
    dp[cur][0] = 1;
    for(int i = 0; i < m; i++) {
      // printf("i=%d\n",i);
        memset(dp[nxt],0,sizeof(dp[nxt]));
        for(int j = 0; j < (1<<15); j++) if(dp[cur][j]){
            if(j&1) {Add(dp[nxt][j>>1] , dp[cur][j]); continue;}
            for(int k = 1; k <= 15; k++) if(i+k < m && g[i][i+k] && !( j&(1<<k) ) ) {
                int mask = ( j | (1 << k) )>> 1; 
                Add(dp[nxt][mask] , dp[cur][j]);
            }
        }
        std::swap(cur,nxt);
    }
    return dp[cur][0];
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值