poj 2923(状态压缩dp)
题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数。
分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法:
1.组合解决:
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; int n,sum1,sum2,a[];
int st1[],st2[],st[],num1,num2,num;
int total[],all;
//st1数组保存的是第一辆车能够一次运走的所有状态,同理st2数组为第二辆车的
//st数组保存的是两辆车一次能够运走的所有状态
void dfs(int f,int flag,int x,int s)//开始的时候这个dfs是作死的错,说明dfs写得还不够熟练
{
int i,j,temp;
if(flag==&&f==n+)
st1[num1++]=x;
else if(f==n+)
st2[num2++]=x;
if(f>n) return ;
temp=<<(n-f);
if(flag==)
{
if(s+a[f]<=sum1)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
else
{
if(s+a[f]<=sum2)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
} void hebing()//两辆车的状态合并
{
int i,j,t=;
int visited[],temp;
memset(visited,,sizeof(visited));
for(i=;i<num1;i++)
for(j=;j<num2;j++)
{
temp=st1[i]|st2[j];
if(visited[temp]==)
{
st[num++]=temp;
visited[temp]=;
}
}
} void solve(int T)//我这里是用组合解决的,虽然提交了之后发现用组合比用背包时间还少
{ //但是觉得可能是测试数据的原因,个人觉得还是背包靠谱些
printf("Scenario #%d:\n",T);
int temp[],t,res=,x;
int i,j,max=,flag=;
int visited[];
all=;total[]=;
for(i=;i<=n;i++)
max=max+(<<(i-));
while()
{
res++;t=;
memset(visited,,sizeof(visited));
for(i=;i<all;i++)
{
// int kao=0;
//kao++;
for(j=;j<num;j++)
{
x=(total[i]|st[j]);
if(x==max)
{
flag=;
break;
}
if(visited[x]==)
{
visited[x]=;
temp[t++]=x;
}
}
if(flag==)
break;
}
if(flag==)
break;
for(i=;i<t;i++)
total[i]=temp[i];
all=t;
}
printf("%d\n",res);
} int main()
{
int i,T,t;
scanf("%d",&T);
for(t=;t<=T;t++)
{
num1=;
num2=;
num=;
scanf("%d%d%d",&n,&sum1,&sum2);
for(i=; i<=n; i++)
scanf("%d",&a[i]);
dfs(,,,);
dfs(,,,);
hebing();
solve(t);
if(t!=T)
printf("\n");
}
return ;
}
2.背包解决:
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; int n,sum1,sum2,a[];
int st1[],st2[],st[],num1,num2,num;
int total[],all; void dfs(int f,int flag,int x,int s)
{
int i,j,temp;
if(flag==&&f==n+)
st1[num1++]=x;
else if(f==n+)
st2[num2++]=x;
if(f>n) return ;
temp=<<(n-f);
if(flag==)
{
if(s+a[f]<=sum1)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
else
{
if(s+a[f]<=sum2)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
} void hebing()
{
int i,j,t=;
int visited[],temp;
memset(visited,,sizeof(visited));
for(i=;i<num1;i++)
for(j=;j<num2;j++)
{
temp=st1[i]|st2[j];
if(visited[temp]==)
{
st[num++]=temp;
visited[temp]=;
}
}
} int Min(int x,int y)
{
return x>y?y:x;
} void solve(int T)
{
printf("Scenario #%d:\n",T);
int i,j,dp[];
for(i=;i<(<<n);i++)
dp[i]=;
dp[]=;
for(i=;i<num;i++)
{
for(j=(<<n)-;j>=;j--)
{
if(dp[j]==)
continue;
if((j&st[i])==)
dp[j|st[i]]=Min(dp[j|st[i]],dp[j]+);
}
}
printf("%d\n",dp[(<<n)-]);
} int main()
{
int i,T,t;
scanf("%d",&T);
for(t=;t<=T;t++)
{
num1=;
num2=;
num=;
scanf("%d%d%d",&n,&sum1,&sum2);
for(i=; i<=n; i++)
scanf("%d",&a[i]);
dfs(,,,);
dfs(,,,);
hebing();
solve(t);
if(t!=T)
printf("\n");
}
return ;
}
poj 2923(状态压缩dp)的更多相关文章
- POJ 1185 状态压缩DP(转)
1. 为何状态压缩: 棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围.故想到用int s[num].至于开多大的数组,可以自己用DFS搜索试试看:也可 ...
- POJ 1185 状态压缩DP 炮兵阵地
题目直达车: POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...
- poj 2688 状态压缩dp解tsp
题意: 裸的tsp. 分析: 用bfs求出随意两点之间的距离后能够暴搜也能够用next_permutation水,但效率肯定不如状压dp.dp[s][u]表示从0出发訪问过s集合中的点.眼下在点u走过 ...
- Mondriaan's Dream(POJ 2411状态压缩dp)
题意:用1*2的方格填充m*n的方格不能重叠,问有多少种填充方法 分析:dp[i][j]表示i行状态为j时的方案数,对于j,0表示该列竖放(影响下一行的该列),1表示横放成功(影响下一列)或上一列竖放 ...
- poj 2411 状态压缩dp
思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个.这样就可以先把所有的合法状态找到.由于没一层的合法状态都是一样的,那么可以用一个数组保存.由第i-1行到第i行的状态转 ...
- poj 3254 状态压缩DP
思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k]: 这个方程得 ...
- POJ 3254 状态压缩 DP
B - Corn Fields Crawling in process... Crawling failed Time Limit:2000MS Memory Limit:65536KB ...
- poj 2923(状态压缩+背包)
比较巧妙的一道题目,拿到题目就想用暴力直接搜索,仔细分析了下发现复杂度达到了2^n*n! ,明显不行,于是只好往背包上想. 于是又想二分找次数判断可行的方法,但是发现复杂度10^8还是很悬... 然后 ...
- POJ 3691 (AC自动机+状态压缩DP)
题目链接: http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...
随机推荐
- android-exploitme(三):安全连接
今天我来测试连接的安全,数据是否可嗅探. android模拟器提供了内置的tcpdump,我们使用这个来抓包. 1. 启动带tcpdump的模拟器 santoku@santoku-virtual-ma ...
- C# 访问USB(HID)设备
原文:C# 访问USB(HID)设备 二话不说,直接给代码,如果您真想做这方面的东西,还是稍微研究下,没有现成的好类用,就需要自己了解其原理 //引用空间 using System; using Sy ...
- Spring MVC配置DispatcherServlet的url-pattern
在配置Spring MVC的核心过滤器DispatcherServlet的url-pattern时是有要求的. <servlet> <servlet-name>...</ ...
- oracle11g OEM无法连接到数据库实例解决办法
我的电脑是32位的win7家庭版系统,那么这样的系统能不能装上oracle呢?能的!就是可能会出错,在装oracle时,每个人遇到的问题都不同,有的人装了双系统,有的人重做了系统,真心酸,先让电脑断网 ...
- python 调用 C++ code
本文以实例code讲解python 调用 C++的方法. 1. 如果没有参数传递从python传递至C++,python调用C++的最简单方法是将函数声明为C可用函数,然后作为C code被pytho ...
- android 更改avd路径
第一种方法,适合还没有建立 AVD 的情况 即:在计算机右击的属性 选择环境变量,然后添加一个用户的环境变量,名字为 "ANDROID_SDK_HOME”,然后把变量值改为你想将" ...
- poj-3616 Milking Time (区间dp)
http://poj.org/problem?id=3616 bessie是一头工作很努力的奶牛,她很关心自己的产奶量,所以在她安排接下来的n个小时以尽可能提高自己的产奶量. 现在有m个产奶时间,每个 ...
- 《OD学Sqoop》数据转换工具Sqoop
一. 第二阶段课程回顾 hadoop 2.x HDFS YARN MapReduce Zookeeper Hive 二.大数据协作框架 对日志类型的海量数据进行分析 hdfs mapreduce/hi ...
- Oracle数据库之一
数据库(oracle) SQL --结构化查询语言,所有数据库基本通用 数据库是数据的仓库,用于存储数据. 内存.文件和数据库区别 内存中的数据是非持久的,关机之后就会消失. 文件和数据库中的数据都是 ...
- 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)
参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...