[USACO][DAG上的动态规划]Sorting A Three-Valued Sequence

好美的图论,真的 light up my life!
题意:

给出一个只含有若干1,2,3的数列,我们可以两两交换数列元素;要求输出让这个数列不减的最小交换次数。

思路:

首先看起来很像冒泡.....然鹅要最少交换次数——显然不是模拟冒泡了。

开始用深搜来着,显然没办法剪枝,果断T掉。这个时候就要想一想图论了。

想起来leetcode周赛的1247这道题。题目说的是有两个在{x,y}上相同长度的字符串,我们可以在两个字符串之间任选字符交换。求第一个字符串变成第二个字符串所需要的最小交换次数,有一点点相似~

那道题用的是把原数列和目标状态对比,统计x-y,y-x的个数。a,b都是偶数则恰好交换完(交换次数为 x/2+y/2),ab奇偶不同则无解,ab都是奇数则最后会剩下一堆x-y,y-x,需要额外两次操作(x/2+y/2+2)。

感觉这种自由交换都少不了目标态和原态之间对比~这道题也是已知了目标状态,但是是交换自己的字符。也是把当前字符串和目标串比较,就会发现有1-2,1-3,2-1,2-3,3-1,3-2这几种需要处理的情况。这就很像图的边的样子不是嘛!所以我们可以创造一个有向图,顶点为1,2,3,两两顶点都有有向边,边权为对比后算出1-2,2-1这种的数量。这样子,如果1-2和2-1的话就可以直接换掉这两个,交换次数加一。处理完所有重边就可以得到一个没有重边的图,这个图一定是个环,并且环上的边权都相等(因为这是一个必定可解的问题啊)。环是什么意思呢?是要交换两次才能摆平的意思哦~比如1-3,3-2,2-1,就是要把231变成123的意思,需要231->132->123;或者另一个方向的环3-1,1-2,2-3,是把312变成123,需要312->132->123这样。

是不是很巧妙!

代码:

/*
ID :ggy_7781
TASK :sort3
LANG :C++11
*/
#include <bits/stdc++.h>

using namespace std;

int a[1007];
int b[1007];
int N;
int edges[4][4];

int main(void)
{
    freopen("sort3.in","r",stdin);
    freopen("sort3.out","w",stdout);
    cin>>N;
    for(int i =0 ;i < N;i ++)
    {
        cin>>a[i];
        b[i] = a[i];
    }
    sort(b,b+N);

    for(int i = 0;i < N;i ++)
    {
        if(a[i] != b[i])
            edges[a[i]][b[i]] ++;
    }
    int ret = 0;
    for(int i = 1;i <= 3;i ++)
    {
        for(int j = 1;j<= 3;j ++)
        {
            int sub = min(edges[i][j],edges[j][i]);
            ret += sub;
            edges[i][j] -= sub;
            edges[j][i] -= sub;
        }
    }
    ret += 2* (edges[1][3] + edges[3][1]);
    cout<<ret<<endl;

    return 0;
}

原文地址:https://www.cnblogs.com/ggy778/p/12231356.html

时间: 2024-10-01 02:53:09

[USACO][DAG上的动态规划]Sorting A Three-Valued Sequence的相关文章

ACM:DAG上的动态规划------硬币问题

ExecutorService 建立多线程线程池的步骤: 线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量,其他线程排队等候.一个任务执行完毕,再从队列的中取最前面的任务开始执行.若队列中没有等待进程,线程池的这一资源处于等待.当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了:否则进入等待队列. 为什么要用线程池: 1.减少了创建和

UVa 103 Stacking Boxes --- DAG上的动态规划

UVa 103 题目大意:给定n个箱子,每个箱子有m个维度, 一个箱子可以嵌套在另一个箱子中当且仅当该箱子的所有的维度大小全部小于另一个箱子的相应维度, (注意箱子可以旋转,即箱子维度可以互换),求最多能套几个箱子. 第一行输入为n,m,之后是n行m维的箱子 解题思路:嵌套关系是二元关系,因此这题即在DAG上做动态规划, 只不过将二维的判断改成了n维,其他不变. 详细看考:DAG上的动态规划之嵌套矩形  (ps:这题可以理解成嵌套m边形) /* UVa 103 Stacking Boxes --

嵌套矩形——DAG上的动态规划

有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 题目描述: 有n个矩形,每个矩形可以用两个整数a,b描述,表示它的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩形X旋转90°).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)内.你的任务是选出尽可能多的矩形排成一行.使得除了最后一个之外,每个矩形都

Monkey and Banana(DAG上的动态规划问题)

Monkey and Banana Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8122    Accepted Submission(s): 4194 Problem Description A group of researchers are designing an experiment to test the IQ of a

DP入门(2)——DAG上的动态规划

有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.DAG模型 [嵌套矩形问题] 问题:有n个矩形,每个矩形可以用两个整数a.b描述,表示它的长和宽.矩形X(a , b)可以嵌套在矩形Y(c , d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩形X旋转90°).例如(1,5)可以嵌套在(6, 2)内,但不能嵌套在(3, 4)内.你的任务是选出尽可能多的矩形排

The Tower of Babylon UVA - 437 DAG上的动态规划

题目:题目链接 思路:每个方块可以用任意多次,但因为底面限制,每个方块每个放置方式选一个就够了,以x y为底 z 为高,以x z为底 y 为高,以y z为底 x为高,因为数据量很小,完全可以把每一种当成DAG上的一个结点,然后建图找最长路径. AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <cs

DAG上的动态规划

UVA1025 分析:因为时间是单向流逝的,是天然的"序",所以影响决策的只有当前时间和所处的决策.dp[i][j],表示在第i分钟时,处于第j个车站,最少还需要多少等待时间,因此其等待时间就有站原地等待,乘坐从左到右的车,乘坐从右到左的车,三个状态来决定. 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "strin

[CF225C] Barcode (简单DAG上dp)

题目链接:http://codeforces.com/problemset/problem/225/C 题目大意:给你一个矩阵,矩阵中只有#和.两种符号.现在我们希望能够得到一个新的矩阵,新的矩阵满足每一列都只有一种符号,并且连续相同符号的列数在区间[x,y]之间. 解: 现将列中的点统计出来,然后就是枚举把列数在x到y之间的需要更改为点的统计出来.这些点染上白色. 然后再将列数在x到y之间的需要更改为井号的点数统计出来,这些点染成黑色. 接下来就是DAG上的动态规划了,dp[i]代表从i到终点

DAG上动态规划

很多动态规划问题都可以转化为DAG上的最长路,最短路,或路径计数问题. 硬币问题: 有N中硬币,面值分别为v1,v2,v3,……vn,每种都无穷多,给定非负整数S,可以选用多少个硬币,使他们的总和恰好为S.输出硬币数目的最小值和最大值. 解:每种面值看作一个点,表示:还需要凑足的面值.则开始状态为S,目标状态为0:若当前状态为i,当使用硬币j后,状态转为i-v[j]. 代码说明好了. 1 #include <iostream> 2 #include <cstdio> 3 #incl