状态DP -- HiHoCoder 1170 Robots
来源:互联网 发布:淘宝店铺大图怎么做 编辑:程序博客网 时间:2024/06/14 21:30
#1170 : Robots
- Sample Input
34 21 2 1 26 42 1 4 3 1 28 61 3 2 5 5 4 5 2
- Sample Output
Case #1: 1Case #2: 6Case #3: 5
Description
XiaoIce has N brothers who are also robots. The robots are now standing in a line. Each of them is assigned with a color. XiaoIce wants them to rearrange their positions so that robots with the same color stand together. In other words, any robot between any two robots with the same color is also assigned with that color.
Provided that only adjacent robots can be swapped, what is the minimum number of swappings to achieve the goal?
Input
The first line contains an integer T, indicating the number of test cases.
Each test case contains two lines.
The first line contains two integers N and K, indicating the number of robots and the number of distinct colors.
The second line contains N integers, and the ith number is the color of the ith robot ranging from 1 to K inclusively.
Output
For each test case, output a line containing "Case #X: Y". X is the test case number starting from 1, and Y is the answer.
Limits
1 ≤ T ≤ 20
1 ≤ N ≤ 105
Small
1 ≤ K ≤ 3
Large
1 ≤ K ≤ 16
初次看这道题,“最少”让我想到了贪心、网络流和DP,“1 ≤ N ≤ 105”让我想到了贪心和线性DP,“1 ≤ K ≤ 16”让我想到了搜索和状态DP(一般看到某个数据小于等于20,题目还是让求最优或者是方案数的都要往状态DP那里考虑一下。命中的概率还是不小的)
由于我这个人特别懒,所以我先考虑了贪心的方法。但是这道题里根本抽不出来小的情形,没办法进行局部贪心。各个数之间都是相关联的,自然也没办法从前往后撸一遍。所以贪心和线性DP被枪毙了。至于搜索和网络流那简直就是在扯淡。
真不开心。。。。。又是状态DP题。好吧,虽然无比蛋疼但是还是要坦然面对。对于这道状态DP,那就直接定义dp[1<<k](说的好像还能有别的定义方法似的 = 皿 = )。中间的数作为状态,化为二进制后如果某一位是1,则表示这种颜色必须被安排好。如果是0则表示这种颜色被忽略,不做考虑。最终的答案当然就是dp[(1<<k)-1]啦。
我们可以很容易的知道如何进行转移。对于当前要求出来的dp[x],枚举一种处在x内的颜色m,然后看dp[x - (1 << m)]要如何转移到dp[x].
虽然大家都知道DP当然是要满足无后效性的,但是在考虑的情况比较多的时候还是有可能弄混乱。
言归正传,dp[x - (1 << m)] 转移到dp[x]一定是要加上一个额外的值的。这个值就是 为了把颜色m从x的状态中抽出来并组成一段连续的序列所需要的总步数tt。
那么我们把tt解决掉就可以了。
tt要如何做呢? 只要枚举x中包含的其他的颜色,然后看为了把颜色j从这些颜色中剥离开来用到的总次数就行了。总次数就是每个颜色代码后面的j颜色代码的数量和。
说起来拗口了一点,直接看代码吧。
#include<iostream>#include<string.h>#include<stdio.h>#include<algorithm>#include<climits>#define inf LONG_LONG_MAXusing namespace std;int pre[20][20],x[20];long long int dp[(1<<17) + 5];int T,n,k;void init(){memset(tot,0,sizeof(tot));memset(pre,0,sizeof(pre));memset(dp,0,sizeof(dp));cin>>n>>k;for(int i = 1;i<=n;i++){int t;cin>>t;t--;for(int j = 0;j<k;j++)pre[j][t] += x[j];x[t]++;}}int main(){cin>>T;for(int zxc = 1;zxc<=T;zxc++){init();dp[0] = 0;dp[0] = 0;for (int i = 1; i < (1 << k); i++) {dp[i] = 1LL * n * n;for (int j = 0; j < k; j++)if (i & (1 << j)) {long long tt = 0;for (int p = 0; p < k; p++)if ((i & (1 << p)) && p != j) tt += pre[p][j];dp[i] = min(dp[i], dp[i - (1 << j)] + tt);}}printf("Case #%d: %lld\n", zxc, dp[(1 << k) - 1]);}return 0;}
我的语言表达能力还是弱了点。如果没有看懂的话,欢迎留言讨论!
- 状态DP -- HiHoCoder 1170 Robots
- 【hihocoder】状态压缩dp
- hihocoder 1044 状态压缩dp
- hihocoder #1044 状态压缩dp
- Hihocoder 1044 DP状态压缩
- hihocoder-第八周-dp状态压缩
- hihocoder#1044状态压缩dp+滚动数组
- [hihocoder]:1048 状态压缩二(状压DP)
- hihoCoder 1498 Diligent Robots
- 【DP】 hihocoder #1170 : 机器人
- hihocoder 1044 状态压缩·一 (状态dp)
- hihoCoder 1170 机器人 (状压dp)
- hihoCoder 1044 状态压缩·一 (状压dp)
- hihocoder-1048 状态压缩·二(状压DP)
- hihocoder#1044 : 状态压缩·一(状压dp)
- hihoCoder 1044 : 状态压缩·一 状压dp
- 【HDU】5837 Robots【DP】
- hihocoder 状态压缩二
- iOS push跳转页面时,页面透明交叉的问题。
- CSS margin重叠问题
- Gradle 构建 android 应用常见问题解决指南
- ALAssetsLibrary-代码操作iOS相册资源
- Windows下安装PHP的mongo扩展
- 状态DP -- HiHoCoder 1170 Robots
- linux下用valgrind检查程序内存泄漏
- php 参数优化
- 看不见的大猩猩--读书笔记
- Android利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件
- Luence5分钟快速入门示例
- Maven项目打包杂谈
- Adapter万能适配器,只要3行
- CMake指令集锦