Travelling (三进制+状压dp)】的更多相关文章

题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ ,f=;char ch=getchar(); ;ch=getchar();} +ch-';ch=getchar();} return x*f; } /***********************************************************/ int n, m; // n < =…
题意 Sol 这好像是我第一次接触三进制状压 首先,每次打完怪之后吃宝石不一定是最优的,因为有模仿怪的存在,可能你吃完宝石和他打就GG了.. 因此我们需要维护的状态有三个 0:没打 1:打了怪物 没吃宝石 2:打了怪物 吃了宝石 如果我们能知道打了那些怪,吃了那些宝石,那么此时的状态时确定的,预处理出来 然后DP就行了 mdzz这题卡常数 /* 首先打完怪之后吃宝石不一定是最优的 因此我们需要枚举出每个怪物的状态 0:没打 1:打了怪物 没吃宝石 2:打了怪物 吃了宝石 如果我们能知道打了那些怪…
N个城市,M条道路,每条道路有其经过的代价,每一个城市最多能够到达两次,求走全然部城市最小代价,起点随意. 三进制状压.存储每一个状态下每一个城市经过的次数. 转移方程: dp[i+b[k]][k]=Min(dp[i+b[k]][k],dp[i][j]+dis[j][k]); #include "stdio.h" #include "string.h" const int inf=0x3f3f3f3f; int b[15],mark[60010][15],dp[60…
题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp 相同. 但,因为是每个点 至多可以经过两次,所以应该用 三进制 来表示状态. 因为三进制不能直接通过移位来表示,所以要 预处理 出每个数字\(state\)的三进制表示中每一位\(i\)上的值\(dig[state][i]\). 注意…
Travelling After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can…
Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3789    Accepted Submission(s): 1182 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is…
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&page=show_problem&problem=1758 状态压缩的DP,dp[i][st]表示状态为st考虑后面i个人所有人最小花费, 因为每个科目有三种状态,可以用一个三进制数表示, 状态不是很多,所以可以把预先把每个数的三进制预处理出来, 决策为选和不选. #include<bits/std…
题目传送门 题意:从某个点出发,所有点都走过且最多走两次,问最小花费 分析:数据量这么小应该是状压题,旅行商TSP的变形.dp[st][i]表示状态st,在i点时的最小花费,用三进制状压.以后任意进制状压都会了. #include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int N = 11; int dp[60000][10]; int bit[N]; int d[N][N]; int p[…
传送门 E. Anya and Cubes time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Anya loves to fold and stick. Today she decided to do just that. Anya has n cubes lying in a line and numbered from 1…
题目大意: 现在给你一个有n个点和m条边的图,每一条边都有一个费用,每个点不能经过超过两次,求所有点至少遍历一次的最小费用 其中n<=10 m没有明确限制(肯定不会超过1e5) 一看到这个数据范围,第一想法就是状压QWQ 但是转念一想,woc,每个点不一定只经过一次咯. woc,那不就是三进制状压?! 好的,至此,这个题成功的成为了我人生中的第一道三进制状压 f[S][i]表示已经走过的点的集合是S 当前在i的最小费用 首先,我们要先预处理一个num数组 num[i][j]表示i这个数的三进制拆…
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目: 题意:n个城市,m条边,每条边都有一个权值,问你经过所有的城市且每条边通过次数不超过两次的最短距离. 思路:状压dp+三进制,dp[i][j]表示在状态i下以j为目标城市的最短距离,转移方程为nw = i + fi[k];dp[nw][k] = min(dp[nw][k], dp[i][j] + mp[j][k]). 代码实现如下: #include <set> #include &…
数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100\) Input Format 一行两个整数n,m. Output Format 一行一个整数表示答案对998244353取模的结果. Sample Input 1 1 Sample Output 1 解析 大致题意:给定一个位数不超过\(20\)位的正整数\(n\),求\(n\)的互异排列中有多少…
Balanced Numbers Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced number if: 1)      Every even digit appears an odd number of times in its decimal representation 2)      Every odd digit app…
题意:n*m方格,有些格子有黑点,问你最多裁处几张2 * 3(3 * 2)的无黑点格子. 思路:我们放置2 * 3格子时可以把状态压缩到三进制: 关于状压:POJ-1038 Bugs Integrated, Inc. (状压+滚动数组+深搜 的动态规划),写的很详细 所以我们直接枚举每一行的所有可能状态,并算出每种状态最大值.这样我们到最后只要找到n行所有状态最大值就行了. 代码: #include<cmath> #include<stack> #include<queue&…
题目链接[http://poj.org/problem?id=1038] 题意: 给出一个N*M大小的图,图中有K个坏点.N (1 <= N <= 150), M (1 <= M <= 10), K (0 <= K <= MN):用2*3和3*2的木块去填这个图,问最多能放多少个木块. 题解:用一个三进制数表示某一行的状态,如果pos位置是0:表示该位置被占用了,pos位置是1:表示该位置没有被占用但是上一层的pos位置被占用了,pos位置是2:表示该位置和上一层的该位…
题目 解法 看到这道题,我们就会想到旅行商问题.但是这里每一个点可以经过最多两次,所以我们用三进制表示就好了. 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <cctype> #include <vector>…
题目:HDU3001 #include <bits/stdc++.h> using namespace std; ],vis[][],dis[][]; ][]; void init()//预处理三进制状态 { state[]=; ;i<=;i++) state[i]=state[i-]*;//最多10个点,要处理到11 ;i<=state[];i++) { int tmp=i; ;j<=;j++){// 把10位都处理一下 vis[i][j]=tmp%; tmp/=; } }…
题目链接: http://codeforces.com/gym/101194/attachments https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5930 题意: 现有四支队伍两两打比赛,总共就是打六场比赛,每场比赛赢的队伍可得 $3$ 分,输的队伍得 $0$ 分,平局则两个队各得 $1$ 分. 现在给出四个队伍最终的积分…
题意:10个点,若干条边,边有花费,每个点最多走两次,求走过所有点,花费最少 分析:因为每个点最多走两次,所以联想到3进制,然后枚举状态,就行了(我也是照着网上大神的代码写的) #include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <vector> #include <string> #include <cmath…
题意:tsp问题,但是每个点可以最多走两次 链接:点我 转移方程见代码 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define inf 0x3f3f3f3f ]; ][]; ][]; ][]; int n,m; void Initiate() { State[]=; ;i<=;i++) State[i]=…
传送门 状压dp好题. 首先需要回忆O(nlogn)O(nlog n)O(nlogn)求lislislis的方法,我们会维护一个单调递增的ddd数组. 可以设计状态f(s1,s2)f(s1,s2)f(s1,s2)表示选取的数的集合是s1s1s1,然后d数组中元素的出现情况是s2s2s2. 这样转移是很简单的. 但时空都无法承受. 于是我们考虑优化,不难发现s1s1s1是s2s2s2的子集. 因此我们三进制状压dp就行了. 代码…
题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i][S]\)表示独立集大小为\(i\),不可选集合为\(S\)[要么是已经在独立集中,要么已经被排除了] 那么剩余点都是可选的 就枚举剩余点\(u\),记\(u\)相邻的集合为\(S_u\),那么当\(u\)加入后,集合\(S_u\)的点都不能选,但是由于所有点都会加入排列之中,\(S_u\)中除了\…
题意: 走n个城市, m条路, 起点任意, 每个城市走不超过两次, 求最小花费, 不能走输出-1. $1\le n\le 10$ 分析: 每个城市的拜访次数为0 1 2, 所以三进制状压, 先预处理10位(n最大为10)的三进制数 ], vis[][]; void init() { num[]=; ; i<=; i++) num[i]=num[i-]*; memset(vis, -, sizeof(vis)); ; i<=num[]; i++) { int x=i; ; j<=; j++…
前言 最近,决定好好恶补一下我最不擅长的\(DP\). 动态规划的种类还是很多的,我就从 状压\(DP\) 开始讲起吧. 简介 状压\(DP\)应该是一个比较玄学的东西. 由于它的时间复杂度是指数级的(但也足以吊锤\(DFS\)),所以状压\(DP\)题的数据范围一般都巨小. 前置技能:位运算 要想学习状压\(DP\),最好先去学一学位运算及其简单变换操作,因为位运算在状压\(DP\)中起到了很重要的作用. 核心思想 状压\(DP\)的核心思想在于用一个变量\(state(0≤state<2^N…
题目传送门 https://loj.ac/problem/6177 题解 一直不知道允不允许这样的情况:取了第一的任务的货物后前往配送的时候,顺路取了第二个货物. 然后发现如果不可以这样的话,那么原题就是一个 \(O(n^3+q^2)\) 算法就能过的题,和数据范围远远不搭配. 所以显然是允许的.根据这个数据范围,我们很容易想到状压每一个任务目前的状态:要么是还没有被接货,要么是在运送途中,要么是运送完成,这三种情况.直接用三进制状压一下,设 \(dp[S][i]\) 表示达到 \(S\) 中的…
T1 传送门 解题思路 发现有一个限制是每个字母都必须相等,那么就可以转化成首尾的差值相等,然后就可以求出\(k-1\)位的差值\(hash\)一下.\(k\)为字符集大小,时间复杂度为\(O(nk)\). 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<map> using namespace std; typedef unsig…
LINK:#6177.美团 送外卖2 一道比较传统的状压dp题目. 完成任务 需要知道自己在哪 已经完成的任务集合 自己已经接到的任务集合. 考虑这个dp记录什么 由于存在时间的限制 考虑记录最短时间 因为时间越短 对于任务来说越优. 考虑设f[i][j][k]表示已经做完的任务为i接受的任务为j上次做的任务为k. 虽然看起来状态数为\(2^q\cdot 2^q\cdot q\)但是考虑j枚举的只是i的补集的子集 所以这样做状态数为\(3^q\cdot q\) 复杂度需要多乘一个q枚举决策 \(…
传送门 三进制状压感觉有点难写啊. 不过这题状态转移方程挺简单的. 就直接f[i][j]表示前i行第i行状态为j时的选法总数,分情况转移就行了. 代码: #include<bits/stdc++.h> #define ll long long #define mod 1000000 #define N 10005 using namespace std; int n,m,K,ban,ans=0,sta[1005],tot=0,stat,f[N][1005],bit[6],pos; inline…
很显然这是一道状压dp的题目 由于每个最优子结构和前两行有关,一个显而易见的想法是用三维dp[i][j][k]用来记录在第i行下为j状态,i - 1行为k状态时的最大值,然而dp[100][1 << 11][1 << 11]显然是要MLE的,我们可以想到用滚动数组优化,事实上确实可以用滚动数组优化.然而 在时间复杂度上 100 * 1024 * 1024 * 1024也是一个不可能补TLE的数字,一个不那么显然的办法是预处理出所有可行的状态,经过看题解或者写个暴力炸一下之后可以知道…
题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示,3进制可以先将表打出来.在走的时候注意只能走2次,其他的和普通的TSP状压DP是一样的.注意点:重边,自环等等,老梗了. //#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include &…