状态压缩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. Wex5铛铛开发环境搭建步骤
  2. 图着色问题贪心算法c语言,区间图着色问题(贪心算法)C++实现
  3. qsort()与sort的用法(收藏)
  4. 微服务架构---幂等机制
  5. (二十五)【NIPS 2017】Prototypical Networks for Few-shot Learning
  6. Leetcode+牛客网—回文串总结(一)
  7. 多多自走棋服务器不稳定,多多自走棋突然宣布停服,数据将全部转移到腾讯服务器中...
  8. 华三路由器RIP协议详细配置
  9. [渝粤教育] 西南科技大学 语文教材教法 在线考试复习资料2021版
  10. 高德纳:盖茨亲自为他的书做推广
  11. Python3 计算空气质量指数AQI
  12. 深入理解SHA系列加密算法
  13. MEC与C-V2X融合应用场景白皮书
  14. 安卓物联网APP开发——基于编辑物联网平台环境实现远程控制数据传输
  15. PyTorch常用的张量创建、变形及运算总结(速查表)
  16. Classic BADI总结
  17. 全角半角符号引发的Entity Framework奇遇记
  18. Linux的rsa命令,openssl命令行进行RSA加密解密
  19. 全面认识Flash技术
  20. 韩称将强化对中国专属区内苏岩礁“警备”

热门文章

  1. ue4 体积光与体积雾 快速入门
  2. 图灵奖得主John Hopcroft推荐的这本强化学习入门书
  3. 程序员生存环境之乔尔测试
  4. 智慧景区解决方案-最新全套文件
  5. MySQL按 年 月 周 日统计表中的数据
  6. 强大的数学专业工具Maple快速上手
  7. 用数据带你回顾乔丹的职业生涯
  8. 铁塔公司来了:运营商为何需要共建共享?
  9. 天馈 频谱 场强 +定位,手持式信号综合分析仪---TFN AMT950C
  10. xmanagr 注册机执行ubuntu 桌面程序,ubuntu无需安装 桌面环境