1、芯片(chip.pas/cpp)

【问题描述】
企鹅集成电路公司生产了一种大小为 2×3的芯片。每块芯片是从一块大小为N×M的硅
片上切下来的,但由于原材料纯度问题,因而有若干的单位正方形并不能作为芯片的一部分。
企鹅集成电路公司想要知道,给定一块 N×M大小的硅片和坏掉的单位正方形的位置,最
多能使用这块硅片生产多少芯片?

【输入格式】
输入的第一行由一个正整数 D 构成,表示硅片的个数。
随后跟着 D 个数据,每个数据第一行包含三个整数 N,M,K,分别表示硅片的长和宽,
以及硅片坏掉的单位正方形个数。
接下 K 行,每行两个整数 X , Y ,表示单位正方形的坐标。
注:左上角的单位正方形用 (1,1) 表示,右下角的单位正方形用 (N,M) 表示。

【输出格式】
共 D 行,每行一个整数,即最多能切出多少个芯片。

【输入样例】

1
6 6 5
1 4
4 6
2 2
3 6
6 4

【输出样例】
3

【数据范围】
对于 10% 的数据,K=0;
对于另 外10%的数据,1≤M≤5,K≤1;
对于40%的数据,1≤M≤8;
最后一个测试点,空间限制8MB,其余限制64MB。
对于所有数据,1≤D≤5,1≤N≤150,1≤M≤10,0≤K≤M。

好。看一看就发现是状压DP,不会写,写了个搜索拿40分,稳的很。

 #include <cstdio>
#include <cstring> const int N = ; bool vis[N][];
int ans, n, m; inline void read(int &x) {
x = ;
char c = getchar();
while(c > '' || c < '') {
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} inline int getmax(int x, int y) {
int tp = ;
for(int i = x; i <= n; i++) {
for(int j = (i == x) ? y : ; j <= m; j++) {
if(!vis[i][j]) {
tp++;
}
}
}
return tp / ;
} inline bool valid1(int x, int y) {
if(x + > n || y + > m) {
return ;
}
for(int i = x; i <= x + ; i++) {
for(int j = y; j <= y + ; j++) {
if(vis[i][j]) {
return ;
}
}
}
return ;
} inline bool valid2(int x, int y) {
if(x + > n || y + > m) {
return ;
}
for(int i = x; i <= x + ; i++) {
for(int j = y; j <= y + ; j++) {
if(vis[i][j]) {
return ;
}
}
}
return ;
} void DFS(int k, int x, int y) {
if(k > ans) {
ans = k;
}
if(y > m) {
y = ;
x++;
}
if(x > n) {
return;
}
int t = getmax(x, y);
if(k + t <= ans) {
return;
}
for(int i = x; i <= n; i++) {
for(int j = (i == x) ? y : ; j <= m; j++) {
if(valid1(i, j)) {
for(int a = i; a <= i + ; a++) {
vis[a][j] = ;
vis[a][j + ] = ;
}
DFS(k + , i, j + );
for(int a = i; a <= i + ; a++) {
vis[a][j] = ;
vis[a][j + ] = ;
}
}
if(valid2(i, j)) {
for(int b = j; b <= j + ; b++) {
vis[i][b] = ;
vis[i + ][b] = ;
}
DFS(k + , i, j + );
for(int b = j; b <= j + ; b++) {
vis[i][b] = ;
vis[i + ][b] = ;
}
}
}
}
return;
} int main() {
freopen("chip.in", "r", stdin);
freopen("chip_bf.out", "w", stdout);
int T;
read(T);
while(T--) {
int k;
ans = ;
memset(vis, , sizeof(vis));
read(n); read(m); read(k);
for(int i = , x, y; i <= k; i++) {
read(x); read(y);
vis[x][y] = ;
} DFS(, , ); printf("%d\n", ans);
} return ;
}

40分搜索

因为我用了一些奇淫技巧剪枝,是搜索中最稳的。

正解:轮廓线DP。

因为最高只有3,那么我们用三进制。

0 表示第 i 行与 i - 1 行皆为空。

1 表示第 i 行为空,i - 1 行被占用。

2 表示第 i 行被占用,i - 1任意。

转移的时候:枚举 i - 1 行的状态 j ,然后根据 j 推出什么都不放时的第 i 行的状态(即每一位 - 1)

考虑第 i 行每个位置放某个方格的左下角。

DFS转移:从第 i 行第一格开始转移。有三种选择:

放一个竖着的,DFS第三格

放一个横着的,DFS第四格

不放,DFS第二格

以此类推。

滚动数组优化:研究转移代码,发现只用到了 i - 1 行

开两个,用 i & 1

三进制状压:zip和unzip函数,指针的用法:

 inline void unzip(int x, int *a) {
for(int i = m - ; i >= ; i--) {
a[i] = x % ;
x /= ;
}
return;
}
inline int zip(int *a) {
int x = ;
for(int i = ; i < m; i++) {
x = x * + a[i];
}
return x;
}

三进制状压

乱七八糟的知识点...

看代码看代码。

 #include <cstdio>
#include <algorithm>
#include <cstring> const int N = , M = ; int tri[M], f[N][], pre[M], now[M];
int m, n, G[N][M]; inline void unzip(int x, int *a) {
for(int i = m - ; i >= ; i--) {
a[i] = x % ;
x /= ;
}
return;
}
inline int zip(int *a) {
int x = ;
for(int i = ; i < m; i++) {
x = x * + a[i];
}
return x;
} void DFS(int x, int y, int last_ans, int now_sta) {
f[x][now_sta] = std::max(f[x][now_sta], last_ans); /// error : down
if(y + >= m) {
return;
} /// here
DFS(x, y + , last_ans, now_sta);
if(!now[y] && !now[y + ] && !pre[y] && !pre[y + ]) {
now[y] = now[y + ] = ;
int temp = zip(now);
DFS(x, y + , last_ans + , temp);
now[y] = now[y + ] = ;
}
if(y + < m && !now[y] && !now[y + ] && !now[y + ]) {
now[y] = now[y + ] = now[y + ] = ;
int temp = zip(now);
DFS(x, y + , last_ans + , temp);
now[y] = now[y + ] = now[y + ] = ;
}
return;
} int main() {
freopen("chip.in", "r", stdin);
freopen("chip.out", "w", stdout);
tri[] = ;
for(int i = ; i < ; i++) {
tri[i] = tri[i - ] * ;
}
int T;
scanf("%d", &T);
while(T--) {
int k;
scanf("%d%d%d", &n, &m, &k);
memset(f, -, sizeof(f));
memset(G, , sizeof(G));
int x, y;
while(k--) {
scanf("%d%d", &x, &y);
G[x][y - ] = ;
}
for(int i = ; i < m; i++) {
pre[i] = G[][i] + ; /// error : G[1][m]
}
int temp = zip(pre);
f[][temp] = ;
for(int i = ; i <= n; i++) { /// hang
for(int j = ; j < tri[m]; j++) { /// i - 1 : state j
if(f[i - ][j] == -) {
continue;
}
unzip(j, pre);
for(int k = ; k < m; k++) { /// get i state
if(G[i][k]) {
now[k] = ; /// error : now[i]
}
else {
now[k] = std::max(pre[k] - , );/// error : now[i] pre[i]
}
}
temp = zip(now);
DFS(i, , f[i - ][j], temp); /// DFS trans
}
}
int ans = ;
for(int i = ; i < tri[m]; i++) { /// get ans
ans = std::max(ans, f[n][i]);
}
printf("%d\n", ans);
} return ;
}

普通

 #include <cstdio>
#include <algorithm>
#include <cstring> const int N = , M = ; int tri[M], f[][], pre[M], now[M];
int m, n, G[N][M]; inline void unzip(int x, int *a) {
for(int i = m - ; i >= ; i--) {
a[i] = x % ;
x /= ;
}
return;
}
inline int zip(int *a) {
int x = ;
for(int i = ; i < m; i++) {
x = x * + a[i];
}
return x;
} void DFS(int x, int y, int last_ans, int now_sta) {
f[x & ][now_sta] = std::max(f[x & ][now_sta], last_ans); /// error : down
if(y + >= m) {
return;
} /// here
DFS(x, y + , last_ans, now_sta);
if(!now[y] && !now[y + ] && !pre[y] && !pre[y + ]) {
now[y] = now[y + ] = ;
int temp = zip(now);
DFS(x, y + , last_ans + , temp);
now[y] = now[y + ] = ;
}
if(y + < m && !now[y] && !now[y + ] && !now[y + ]) {
now[y] = now[y + ] = now[y + ] = ;
int temp = zip(now);
DFS(x, y + , last_ans + , temp);
now[y] = now[y + ] = now[y + ] = ;
}
return;
} int main() {
freopen("chip.in", "r", stdin);
freopen("chip_bf.out", "w", stdout);
tri[] = ;
for(int i = ; i < ; i++) {
tri[i] = tri[i - ] * ;
}
int T;
scanf("%d", &T);
while(T--) {
int k;
scanf("%d%d%d", &n, &m, &k);
memset(G, , sizeof(G));
memset(f, -, sizeof(f));
int x, y;
while(k--) {
scanf("%d%d", &x, &y);
G[x][y - ] = ;
}
for(int i = ; i < m; i++) {
pre[i] = G[][i] + ; /// error : G[1][m]
}
int temp = zip(pre);
f[][temp] = ;
for(int i = ; i <= n; i++) { /// hang
for(int j = ; j < tri[m]; j++) {
f[i & ][j] = -;
}
for(int j = ; j < tri[m]; j++) { /// i - 1 : state j
if(f[(i + ) & ][j] == -) {
continue;
}
unzip(j, pre);
for(int k = ; k < m; k++) { /// get i state
if(G[i][k]) {
now[k] = ; /// error : now[i]
}
else {
now[k] = std::max(pre[k] - , );/// error : now[i] pre[i]
}
}
temp = zip(now);
DFS(i, , f[(i + ) & ][j], temp); /// DFS trans
}
}
int ans = ;
for(int i = ; i < tri[m]; i++) { /// get ans
ans = std::max(ans, f[n & ][i]);
}
printf("%d\n", ans);
} return ;
}

滚动数组优化空间

这几个错调的真不容易啊......

 #include<bits/stdc++.h>
using namespace std; const int tri[] = {, , , , , , , , , , , };
int n, m, k, dp[][], pre[], now[]; //滚动数组来记录
bool g[][];
int getTen(int *a)//把一个用数组表示的状态转化为一个10进制整数
{
int ans = ;
for(int i = ; i <= m; ++i)
ans += a[i]*tri[i];
return ans;
}
void getTri(int v, int *a)//把一个整数转化为一个数组来表示状态
{
for(int i = ; i <= m; ++i) {
a[i] = v%;
v /= ;
}
}
void dfs(int x, int y, int last, int key)
{
int k;
dp[x&][key] = max(dp[x&][key], last);
if(y >= m) return;
if(!pre[y] && !pre[y+] && !now[y] && !now[y+]) {//竖着切割
now[y] = now[y+] = ;
k = getTen(now);
dfs(x, y+, last+, k);
now[y] = now[y+] = ;
}
if(y<m- && !now[y] && !now[y+] && !now[y+]) { //横着切割 now[y] = now[y+] = now[y+] = ;
k = getTen(now);
dfs(x, y+, last+, k);
now[y] = now[y+] = now[y+] = ;
}
dfs(x, y+, last, key); //不做改动,直接下一行
}
int main()
{
freopen("chip.in","r",stdin);
freopen("chip.out","w",stdout);
int t, a, b, tmp;
scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &n, &m, &k);
memset(g, , sizeof(g));
for(int i = ; i < tri[m+]; ++i) dp[][i] = -;
for(int i = ; i < k; ++i) {
scanf("%d%d", &a, &b);
g[a][b] = ;
}
for(int i = ; i <= m; ++i)
pre[i] = g[][i]+; //设置第一行的状态,第0行的方块全部视为不可用
tmp = getTen(pre);
dp[][tmp] = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j < tri[m+]; ++j) dp[i&][j] = -;
for(int j = ; j < tri[m+]; ++j) {
if(dp[(i+)&][j] == -) continue; //跳过不可能的子状态
getTri(j, pre);
for(int l = ; l <= m; ++l) //根据上一行的状态得到本行的状态
if(g[i][l]) now[l] = ;
else now[l] = max(pre[l]-, );
tmp = getTen(now);
dfs(i, , dp[(i+)&][j], tmp);
}
}
int ans = ;
for(int i = ; i < tri[m+]; ++i)
ans = max(ans, dp[n&][i]);
printf("%d\n", ans);
}
return ;
}

std

chip的更多相关文章

  1. a chip multiprocessor

    COMPUTER OR GANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION A multicore computer ...

  2. hdu5269 Chip Factory

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5536 题目: Chip Factory Time Limit: 18000/9000 MS ( ...

  3. 2015ACM/ICPC亚洲区长春站 J hdu 5536 Chip Factory

    Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  4. codeforces 590B B. Chip 'n Dale Rescue Rangers(二分+计算几何)

    题目链接: B. Chip 'n Dale Rescue Rangers time limit per test 1 second memory limit per test 256 megabyte ...

  5. Codeforces Round #327 (Div. 1) B. Chip 'n Dale Rescue Rangers 二分

    题目链接: 题目 B. Chip 'n Dale Rescue Rangers time limit per test:1 second memory limit per test:256 megab ...

  6. HDU 5536 Chip Factory 字典树

    Chip Factory Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  7. Codeforces Round #327 (Div. 2) D. Chip 'n Dale Rescue Rangers 二分 物理

    D. Chip 'n Dale Rescue Rangers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/co ...

  8. Cheap CK100 1024 tokens NXP FIX Chip on Eobd2

    CK100 is a well-known and cost-effective key programmer for many cars. Some said it is a must for bo ...

  9. HDU 5536 Chip Factory 字典树+贪心

    给你n个数,a1....an,求(ai+aj)^ak最大的值,i不等于j不等于k 思路:先建字典树,暴力i,j每次删除他们,然后贪心找k,再恢复i,j,每次和答案取较大的,就是答案,有关异或的貌似很多 ...

  10. cf590B Chip 'n Dale Rescue Rangers

    B. Chip 'n Dale Rescue Rangers time limit per test 1 second memory limit per test 256 megabytes inpu ...

随机推荐

  1. java随笔2 变量类定义

    如果要定义变量为对象,就要创建此对象对应的java类, 且定义的类型为类名,且都为private

  2. day 7-17 多表查询

    一. 准备表 #部门表 create table dep( id int, name varchar(20) ); #员工表 create table emp( id int primary key ...

  3. spring boot中常用的配置文件的重写

    @Configuration public class viewConfigSolver extends WebMvcConfigurerAdapter { /* spring boot 已经自动配置 ...

  4. java学习之—链表(3)

    /** * 使用链表实现队列 * Create by Administrator * 2018/6/19 0019 * 下午 4:37 **/ public class Link { public l ...

  5. 在windows 7上安装TensorFlow

    TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习.目前被50个团队用于研究和生产许多Google商业产品,如语音识别.Gmail.Google 相册和搜索,其中许多产品曾使用 ...

  6. 八、.net core 通过数据库配置文件连接操作数据库

    一.创建DotNetCore项目 直接创建core项目并不勾选docker支持  二.nuget进行连接MySQL程序集的下载安装 1.MySql.Data.EntityFrameworkCore方式 ...

  7. PHP namespace、require、use区别

    假设 有文件a.php 代码 <?php class a{//类a public function afun()//函数afun { echo "aaaa"; } } ?&g ...

  8. Lodop打印控件 超文本自动分页

    Lodop打印控件打印html超文本,通常传入一个超文本内容可能会超过纸张,如果要拆分每页显示哪些然后手动分页比较麻烦,Lodop中的超文本都有自动分页的特点.自动分页的依据:1.超文本超过设置的打印 ...

  9. MySQL官方教程及各平台的安装教程和配置详解入口

    官方文档入口: https://dev.mysql.com/doc/ 一般选择MySQL服务器版本入口: https://dev.mysql.com/doc/refman/en/ 在右侧有版本选择: ...

  10. HTML5-Input

    HTML5拥有多个新的表单输入类型,这些新特性提供了更好的输入控制和验证(有的浏览器不支持) color.date.datetime.datetime-local.email.month.number ...