UVaLive 6625 Diagrams & Tableaux (状压DP 或者 DFS暴力)
题意:给一个的格子图,有 n 行单元格,每行有a[i]个格子,要求往格子中填1~m的数字,要求每个数字大于等于左边的数字,大于上边的数字,问有多少种填充方法。
析:感觉像个DP,但是不会啊。。。就想暴力试试,反正数据量看起来不大才7,但是。。。TLE了,又换了一个暴力方法,2秒多过了,差点啊。
其实这是一个状压DP,dp[i][s]表示在第 i 列,在集合 s 中有方法数,那么怎么转移呢,这个还是挺简单的,就是判断第i+1列是不是比第 i 列都大于等于就ok了,
输入时先把行,转化成列,再计算,初始化就是第一列喽,假设什么组合都行。
代码如下:
暴力代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define frer freopen("in.txt", "r", stdin)
#define frew freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 450 + 5;
const int mod = 1e9 + 7;
const char *mark = "+-*";
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
int w[10], h[10];
int ans = 0, cnt[10][10]; void dfs(int r, int c, int mx){
if(c > m){
++ans; return ;
}
int mm = Min(n, n-h[c]+r); for(int i = Max(mx+1, cnt[r][c-1]); i <= mm; ++i){
cnt[r][c] = i;
if(r == h[c]) dfs(1, c+1, 0);
else dfs(r+1, c, i);
}
} int main(){
int k;
while(scanf("%d", &k) == 1){
memset(h, 0, sizeof h);
m = 0;
for(int i = 1; i <= k; ++i){
int x;
scanf("%d", &x);
m = Max(m, x);
for(int j = 1; j <= x; ++j)
++h[j];
} scanf("%d", &n);
ans = 0;
memset(cnt, 0, sizeof cnt);
dfs(1, 1, 0);
printf("%d\n", ans);
}
return 0;
}
状压DP代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define frer freopen("in.txt", "r", stdin)
#define frew freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 8;
const int mod = 1e9 + 7;
const char *mark = "+-*";
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} int a[10];
int dp[maxn][1<<maxn]; inline int lowbit(int x){
return x & (-x);
} inline int bitcount(int i){//返回 i 这个数二进制数中有几个1
int ans = 0;
while(i) ++ans, i -= lowbit(i);
return ans;
} inline bool judge(int j, int k){//判断第 j 列是不是小于等于第 k 列
int tj[10], tk[10];
int cntj = 0, cntk = 0;
for(int i = 0; i < m; ++i){
if(j>>i&1) tj[cntj++] = i;
if(k>>i&1) tk[cntk++] = i;
}
for(int i = 0; i < cntk; ++i)
if(tj[i] > tk[i]) return false;
return true;
} int main(){
while(scanf("%d", &n) == 1){
memset(a, 0, sizeof a);
int t = 0, x;
for(int i = 0; i < n; ++i){
scanf("%d", &x);
t = Max(t, x);
for(int j = 1; j <= x; ++j)
++a[j];
} memset(dp, 0, sizeof dp);
scanf("%d", &m);
int len = 1<<m;
for(int i = 0; i < len; ++i)//初始化第 1 列
if(bitcount(i) == a[1]) dp[1][i] = 1; for(int i = 1; i < t; ++i){
for(int j = 0; j < len; ++j){
if(bitcount(j) != a[i] || !dp[i][j]) continue; for(int k = 0; k < len; ++k)
if(bitcount(k) == a[i+1] && judge(j, k)) dp[i+1][k] += dp[i][j];
}
} int ans = 0;
for(int i = 0; i < len; ++i) ans += dp[t][i];
printf("%d\n", ans);
}
return 0;
}
UVaLive 6625 Diagrams & Tableaux (状压DP 或者 DFS暴力)的更多相关文章
- 「状压DP」「暴力搜索」排列perm
「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...
- UVALive 6912 Prime Switch 状压DP
Prime Switch 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8& ...
- hihocoder #1608 : Jerry的奶酪(状压dp)
题目链接:http://hihocoder.com/problemset/problem/1608 题解:就是一道简单的状压dp由于dfs过程中只需要几个点之间的转移所以只要预处理一下几个点就行. # ...
- codeforces Diagrams & Tableaux1 (状压DP)
http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...
- 状压DP uvalive 6560
// 状压DP uvalive 6560 // 题意:相邻格子之间可以合并,合并后的格子的值是之前两个格子的乘积,没有合并的为0,求最大价值 // 思路: // dp[i][j]:第i行j状态下的值 ...
- UVAlive 6560 - The Urge to Merge(状压dp)
LA 6560 - The Urge to Merge option=com_onlinejudge&Itemid=8&page=show_problem&problem=45 ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
随机推荐
- freemarker判断记录集是不是为空
#if($personals)这样写 直接把记录标识符放在if里面就可以了
- 函数flst_remove
移除 node, node->prev直接指向node->next /*********************************************************** ...
- UVa 10088 (Pick定理) Trees on My Island
这种1A的感觉真好 #include <cstdio> #include <vector> #include <cmath> using namespace std ...
- LA 4329 (树状数组) Ping pong
第一次写树状数组,感觉那个lowbit位运算用的相当厉害. 因为-x相当于把x的二进制位取反然后整体再加上1,所以最右边的一个1以及末尾的0,取反加一以后不变. 比如1000取反是0111加一得到10 ...
- HDU 1078 FatMouse and Cheese【记忆化搜索】
题意:给出n*n的二维矩阵,和k,老鼠每次最多走k步,问老鼠从起点(0,0)出发,能够得到的最大的数(即为将每走过一点的数都加起来的和最大)是多少 和上一题滑雪一样,搜索的方向再加一个循环 #incl ...
- [.NET WebAPI系列03] WebAPI Controller 中标准CRUD方法
[因] WebAPI的Controller中,一般都是下面四种方法: 对应于数据操作是我们通常所说的CRUD. C对应post,R对应Get,U对应Put,D对应Delete. 直接模仿VS 2012 ...
- UVA 11294 Wedding(2-sat)
2-sat.不错的一道题,学到了不少. 需要注意这么几点: 1.题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位. 2.2-sat问题是根据必然性建边,比如说A与B ...
- Java中hashcode,equals和==
hashcode方法返回该对象的哈希码值. hashCode()方法可以用来来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的位置,Map在搜索一个对象的时候先通过has ...
- Android设计模式之命令模式、策略模式、模板方法模式
命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从 ...
- NPlot开源画图类
一.net下的图表控件NPlot的基本用法 NPlot的基本用法 图表控件一直是很难找的,特别是免费又强大的.NPlot是一款非常难得的.Net平台下的图表控件,能做各种曲线图,柱状图,饼图,散 ...