谜题59_合并时间段

案例用表如下

CREATE TABLE Timesheets
(task_id CHAR(10) NOT NULL PRIMARY KEY,
 start_date DATE NOT NULL, 
 end_date DATE NOT NULL, 
 CHECK(start_date <= end_date));
 
INSERT INTO Timesheets 
SELECT 1,  to_date('1997-01-01','yyyy-mm-dd'), to_date('1997-01-03','yyyy-mm-dd') from dual union all 
SELECT 2,  to_date('1997-01-02','yyyy-mm-dd'), to_date('1997-01-04','yyyy-mm-dd') from dual union all 
SELECT 3,  to_date('1997-01-04','yyyy-mm-dd'), to_date('1997-01-05','yyyy-mm-dd') from dual union all 
SELECT 4,  to_date('1997-01-06','yyyy-mm-dd'), to_date('1997-01-09','yyyy-mm-dd') from dual union all 
SELECT 5,  to_date('1997-01-09','yyyy-mm-dd'), to_date('1997-01-09','yyyy-mm-dd') from dual union all 
SELECT 6,  to_date('1997-01-09','yyyy-mm-dd'), to_date('1997-01-09','yyyy-mm-dd') from dual union all 
SELECT 7,  to_date('1997-01-12','yyyy-mm-dd'), to_date('1997-01-15','yyyy-mm-dd') from dual union all 
SELECT 8,  to_date('1997-01-13','yyyy-mm-dd'), to_date('1997-01-14','yyyy-mm-dd') from dual union all 
SELECT 9,  to_date('1997-01-14','yyyy-mm-dd'), to_date('1997-01-14','yyyy-mm-dd') from dual union all 
SELECT 10, to_date('1997-01-17','yyyy-mm-dd'), to_date('1997-01-17','yyyy-mm-dd') from dual;

未想到好方法,抛砖引玉而已

select start_date, min(end_date)
  from (select a.start_date, b.end_date
          from timesheets a, timesheets b
         where a.end_date <= b.end_date
           and not exists (select *
                  from timesheets c
                 where a.start_date > c.start_date
                   and a.start_date <= c.end_date
                   and c.task_id != a.task_id)
           and not exists (select *
                  from timesheets d
                 where b.end_date >= d.start_date
                   and b.end_date < d.end_date
                   and d.task_id != b.task_id))
 group by start_date
 order by 1

现在新方法如下,参考自cookbook

with c as
 (select start_date,
         end_date,
         case
           when MAX(end_date) over(order by start_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) >= start_date then
            0
           else
            1
         end as l
    from Timesheets b),
d as
 (select start_date, end_date, sum(l) over(order by start_date) as l from c)
select min (start_date) as start_date, max(end_date) as end_date
  from d
 group by l
 order by 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
三壶谜题是一个经典的逻辑问题,通过使用三个容量不同的水壶,来实现特定容量的水的测量。以下是C++编程实现三壶谜题的一种可能解决方案: ```cpp #include <iostream> #include <queue> #include <set> using namespace std; struct State { int x, y, z; string path; }; void solveThreeJugs(int a, int b, int c, int d) { queue<State> q; set<pair<int, int>> visited; State init = {0, 0, c, ""}; q.push(init); visited.insert(make_pair(0, c)); while (!q.empty()) { State curr = q.front(); q.pop(); if (curr.x == d || curr.y == d || curr.z == d) { cout << curr.path << endl; return; } // 从x壶向y壶倒水 if (curr.x > 0) { int pour = min(curr.x, b - curr.y); State next = {curr.x - pour, curr.y + pour, curr.z, curr.path + "X" + to_string(pour) + "Y"}; if (visited.find(make_pair(next.x, next.y)) == visited.end()) { q.push(next); visited.insert(make_pair(next.x, next.y)); } } // 从x壶向z壶倒水 if (curr.x > 0) { int pour = min(curr.x, c - curr.z); State next = {curr.x - pour, curr.y, curr.z + pour, curr.path + "X" + to_string(pour) + "Z"}; if (visited.find(make_pair(next.x, next.z)) == visited.end()) { q.push(next); visited.insert(make_pair(next.x, next.z)); } } // 从y壶向x壶倒水 if (curr.y > 0) { int pour = min(curr.y, a - curr.x); State next = {curr.x + pour, curr.y - pour, curr.z, curr.path + "Y" + to_string(pour) + "X"}; if (visited.find(make_pair(next.x, next.y)) == visited.end()) { q.push(next); visited.insert(make_pair(next.x, next.y)); } } // 从y壶向z壶倒水 if (curr.y > 0) { int pour = min(curr.y, c - curr.z); State next = {curr.x, curr.y - pour, curr.z + pour, curr.path + "Y" + to_string(pour) + "Z"}; if (visited.find(make_pair(next.y, next.z)) == visited.end()) { q.push(next); visited.insert(make_pair(next.y, next.z)); } } // 从z壶向x壶倒水 if (curr.z > 0) { int pour = min(curr.z, a - curr.x); State next = {curr.x + pour, curr.y, curr.z - pour, curr.path + "Z" + to_string(pour) + "X"}; if (visited.find(make_pair(next.x, next.z)) == visited.end()) { q.push(next); visited.insert(make_pair(next.x, next.z)); } } // 从z壶向y壶倒水 if (curr.z > 0) { int pour = min(curr.z, b - curr.y); State next = {curr.x, curr.y + pour, curr.z - pour, curr.path + "Z" + to_string(pour) + "Y"}; if (visited.find(make_pair(next.y, next.z)) == visited.end()) { q.push(next); visited.insert(make_pair(next.y, next.z)); } } } cout << "无法得到目标容量的水" << endl; } int main() { int a, b, c, d; cout << "请输入三个水壶的容量(以空格分隔):"; cin >> a >> b >> c; cout << "请输入目标容量:"; cin >> d; solveThreeJugs(a, b, c, d); return 0; } ``` 这段代码使用了广度优先搜索算法来遍历所有可能的状态,直到找到目标容量的水或者无法得到目标容量的水。程序会输出一系列操作,其中X表示从x壶倒水,Y表示从y壶倒水,Z表示从z壶倒水。如果无法得到目标容量的水,则输出"无法得到目标容量的水"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值