状态压缩dp

状态压缩dp就是用二进制数字来表示状态,通过遍历所有状态确定答案,时间复杂度为o(nn2^n),通常只能用来解数据范围小于等于21的。
P1433 吃奶酪

#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
/*不要被困在一种思路中
*/
//dp i j 表示在i状态下位于j位跑动的最小距离
double dis[20][20],ans=0xffffffff,dp[35000][20],r[20],c[20];double getdis(int i,int j){return sqrt((r[i]-r[j])*(r[i]-r[j])+(c[i]-c[j])*(c[i]-c[j]));
}int main()
{int n;cin>>n;memset(dp,127,sizeof(dp));for(int i=1; i<=n; i++)cin>>r[i]>>c[i];for(int i=0; i<=n; i++)for(int j=i; j<=n; j++)dis[i][j]=getdis(i,j),dis[j][i]=dis[i][j];for(int i=1; i<=n; i++){dp[1<<(i-1)][i]=dis[0][i];}for(int i=1; i<=(1<<n)-1; i++){for(int j=1; j<=n; j++){if(i&(1<<(j-1))==0)continue;for(int k=1; k<=n; k++){if(j==k)continue;if(i&(1<<(k-1))==0)continue;dp[i][j]=min(dp[i][j],dp[i&~(1<<(j-1))][k]+dis[j][k]);}}}for(int i=1; i<=n; i++){ans=min(ans,dp[(1<<n)-1][i]);}printf("%.2lf",ans);return 0;
}

这个题还可以使用dfs+状态压缩优化来解,可以通过记录状态来做出一个记忆化搜索。当通过的位置确定了,无论是怎么走的,当前所走的最小步数也就确定了。

#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
double bestv=0xffffffff;
int n;
double dp[65000][20];
map<pair<double,double>,int> visit;
pair<double,double> a[20];double getdis(pair<double,double> p1,pair<double,double> p2){return sqrt(pow(p1.first-p2.first,2)+pow(p1.second-p2.second,2));
}void dfs(int i,double now,int bi,pair<double,double> p){if(i==n){bestv=min(bestv,now);return;}for(int j=1; j<=n; j++){//bt记录当前状态int bt=bi|(int)pow(2,j-1);if(visit.find(a[j])->second)continue;if(now+getdis(p,a[j])>=bestv)continue;//剪枝if(now+getdis(p,a[j]) > dp[bt][j])continue;//更新状态dp[bt][j]=now+getdis(p,a[j]);visit.find(a[j])->second=1;dfs(i+1, now+getdis(p,a[j]),bt,a[j]);visit.find(a[j])->second=0;}
/*    for(int j=1; j<=n; j++){if(visit.find(a[j])->second)continue;if(now+getdis(p,a[j])>=bestv)continue;visit.find(a[j])->second=1;dfs(i+1, now+getdis(p,a[j]), a[j]);visit.find(a[j])->second=0;}*/
}/*不要被困在一种思路中
*/int main()
{//freopen("d://P1433_5.in","r",stdin);//freopen("d://out.txt","w",stdout);cin>>n;for(int i=1; i<=n; i++){cin>>a[i].first>>a[i].second;visit.insert(map<pair<double,double>,int>::value_type(a[i],0));}memset(dp,127,sizeof(dp));pair<double,double> t(0,0);dfs(0,0,0,t);printf("%.2lf",bestv);return 0;
}

Game of Ball Passing
看着挺简单的,就是不会。首先如果最大的数有两个及以上,那么一个球满足条件,根据此可以抽出最大的数maxx和剩余数的和sum,如果sum>=maxx,那么一定可以造出两个最大的数。如果小于那么肯定不满足,那么需要maxx-sum个球(此时一个球最多消耗maxx的sum+1)

#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
/*不要被困在一种思路中
*/
void solve(){long long n,a,maxx=-1,sum=0;cin>>n;for(int i=1; i<=n; i++){cin>>a;maxx=max(maxx,a);sum+=a;}sum-=maxx;if(sum >= maxx && sum!=0)cout<<1<<endl;else cout<<maxx-sum<<endl;
}int main()
{int t;cin>>t;while(t--)solve();return 0;
}

Cow Frisbee Team S
0-1背包,因为数据量的问题,需要运用求余小技巧。感觉如果使用一重数组,不论j从小到大还是从大到小,都会变成完全背包,归根结底还是对j取模的原因

#include <bits/stdc++.h>
#define eps 1e-15
#define mod 100000000
using namespace std;
/*不要被困在一种思路中
*/
//dp i j表示选第i头牛,队伍能力为对j取余,的方案数量
long long n,f,a[2005],dp[2005][1005];int main()
{//freopen("d://P2946_2.in","r",stdin);cin>>n>>f;for(int i=1; i<=n; i++)cin>>a[i];dp[0][f]=1;for(int i=1; i<=n; i++){for(int j=0; j<=f; j++){dp[i][j]+=dp[i-1][j];dp[i][(j+a[i])%f]=(dp[i][(j+a[i])%f]%mod+dp[i-1][j]%mod)%mod;}}cout<<dp[n][0]%mod;return 0;
}

质数和分解
完全背包

**#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
/*不要被困在一种思路中
*/
//dp j 表示选完第i个数,剩余数为j的方案数
int n,dp[205];bool judge(int x){if(x==1)return false;bool f=1;for(int i=2; i<=x/2; i++)if(x%i==0){f=0;break;}return f;
}void solve(){dp[n]=1;for(int i=2; i<=n; i++){if(!judge(i))continue;for(int j=n; j>=0; j--){if(j+i>n)continue;dp[j]+=dp[j+i];}}
}int main()
{while(scanf("%d",&n)!=EOF){solve();cout<<dp[0]<<endl;memset(dp,0,sizeof(dp));}return 0;
}**

Buying Hay S
完全背包

#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
/*不要被困在一种思路中
*/
//dp j表示j磅花费的价钱
int n,h,dp[55005],ans=0xfffffff;
pair<int, int> a[105];int main()
{cin>>n>>h;for(int i=1; i<=n; i++)cin>>a[i].first>>a[i].second;memset(dp,127,sizeof(dp));dp[0]=0;for(int i=1; i<=n; i++){for(int j=0; j<=h; j++){dp[j+a[i].first]=min(dp[j+a[i].first], dp[j]+a[i].second);}
/*    for(int i=0; i<=h; i++)cout<<dp[i]<<" ";cout<<endl;*/}for(int i=h; i<=55004; i++)ans=min(ans,dp[i]);cout<<ans;return 0;
}

River Crossing S
0-1背包

#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
/*不要被困在一种思路中
*/
//dp i j表示运完第i头牛后,船上剩下的牛的数量
int dp[2505][2505],a[2505],n,m;
void solve(){int minn;dp[1][0]=m+a[1]+m;dp[1][1]=0;for(int i=2; i<=n; i++){dp[i][0]=dp[i-1][0]+m+a[1]+m;for(int j=1; j<=i-1; j++){//只需要计算每次运完后剩下0头牛的最小值,分为先运j头牛再运第i头牛和一起运j+1头牛dp[i][0]=min(min(dp[i-1][j]+a[j]+2*m+a[1]+2*m,dp[i-1][j]+a[j+1]+2*m),dp[i][0]);}for(int j=1; j<=i; j++)dp[i][j]=dp[i-1][j-1];}minn=dp[n][0]-m;for(int i=1; i<=n; i++)minn=min(dp[n][i]+a[i]+m,minn);cout<<minn;
}int main()
{cin>>n>>m;for(int i=1; i<=n; i++){cin>>a[i];a[i]+=a[i-1];}solve();return 0;
}

状态压缩+dfs+背包相关推荐

  1. 【hdu4281状态压缩+01背包+多旅行商问题】

    题意:有n道题,每道题在二维平面内的不同位置且给出每道题的坐标,同时给出处理每道题所需的时间p,现在已知裁判的耐心有限,之会花费m个单位时间去做事,做完后回到起始点. 现在的要求是,我要多少个裁判才能 ...

  2. uva1507(状态压缩+dfs)

    题意: 给出我们n种物品,每种物品都有五个值,分别是a.b.c.d.e,我们要在这n个物品中选出k个,使得这k个物品中的max{a}+max{b}+max{c}+max{d}+max{e}最大,输出最 ...

  3. OpenJudge - 海贼王之伟大航路(状态压缩+DFS)

    题目链接:http://bailian.openjudge.cn/practice/4124?lang=en_US 总时间限制: 1000ms 内存限制: 65536kB 描述 "我是要成为 ...

  4. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  5. 《算法竞赛进阶指南》打卡-基本算法-AcWing 94. 递归实现排列型枚举:dfs、二进制状态压缩

    文章目录 题目解答 题目来源 题目解答 分析: dfs求全排列,这里是用二进制状态压缩进行优化,二进制状态压缩,顾名思义,每个状态是用二进制的某一位表示.这里的体现是state这个状态,它的每一位代表 ...

  6. 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩

    文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...

  7. 《算法竞赛进阶指南》打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归、二进制状态压缩、dfs

    文章目录 题目解答 题目链接 题目解答 分析: 优化:用二进制状态压缩,也就是用二进制上的位来记录数有没有被用过. ac代码 #include<bits/stdc++.h> using n ...

  8. hdu 3681(bfs+dfs+状态压缩)

    解题思路:这道题属于图上来回走的问题,可以把重复走的过程弱化,即只强调从u->v的结果,中间经过的节点都不考虑.这道题里面'G','F','Y'是重要的节点,其余的点我们是可以忽略的,也就是说, ...

  9. CodeForces - 620E New Year Tree(线段树+dfs序+状态压缩)

    题目链接:点击查看 题目大意:给出一棵无向树,每个节点都有一种颜色,接下来时m次操作: 1 x y:将x及其子树染成y的颜色 2 x:查询x及其子树上共有多少种不同的颜色 题目分析:看完这个题的第一反 ...

最新文章

  1. windows7 端口查看以及杀死进程释放端口
  2. C语言里面%2d 意思
  3. 使用canvas实现360水球波动
  4. LSTM神经网络Demystifying LSTM neural networks
  5. 【ActiveMQ】消息生产者自动注入报错:Could not autowire. No beans of 'JmsMessagingTemplate' type found...
  6. 详解css样式处理的优先级
  7. B10_NumPy数组操作、修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除
  8. 韩研究人员声称:创造出了一块“不可破坏”的芯片!
  9. 《Reids 设计与实现》第十六章 集群(下)
  10. 萌新的Python练习菜鸟100例(十一)生兔子练习
  11. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记
  12. Windows 使用windump进行循环抓包
  13. JVM内存模型1.8
  14. 速锐得驾培驾考免接线OBD数据价值及发展思路
  15. 混合罚函数c语言程序,混合惩罚函数法.ppt
  16. 2019/04/15 在调试https://blog.csdn.net/hjw2719/article/details/83473199中程序时出现的问题
  17. win10支持8t 硬盘_最快最简单!Win10 正式版硬盘安装方法详解
  18. SDN多控制器资源池的设计与实现
  19. VUE:使用element-ui的el-table时,自定义单元格内容,并tab快速切换指定编辑的单元格,而不是把所有能tab切换的都切换一遍
  20. 图欧学习资源库 https://tuostudy.com/

热门文章

  1. 闲鱼选品我使用的4个网站,附赠20个流量密码关键字!
  2. 加深讲解 L4 L7 调度跟apiserver通信
  3. 繁易平台对接阿里云平台: MQTT方式
  4. FL Studio 20无限试用版水果编曲下载
  5. Chromium Mojo IPC
  6. 安装博图V15时出现缺少.net3.5sp1解决办法
  7. Python - 进度条神器 tqdm 用法
  8. 受“头号玩家”的启发,FantaVerse(梵塔世界)正在将OASIS级别的元宇宙变为现实
  9. 网络设备和常见网络拓扑
  10. vue日期组件 日历 日期选择器