天然气
题目描述
Mary 试图控制成都的天然气市场。
专家已经标示出了最好的天然气井和中转站在成都的地图。现在需要将中转站和天然气井连接
起来。每个中转站必须被连接到正好一个钻油井,反之亦然。
Mary 特别指名,建设的天然气管道必须从某个天然气井开始,向南或者向东建设。
Mary 想知道怎么连接每个天然气井和中转站,使得需要的天然气管道的总长度最小。
输入输出格式
输入:
第一行为一个正整数 n,表示天然气井的数量(中转站的数量与之相等)。
接下来 n 行,每行两个整数 x_i 和 y_i,表示天然气井的坐标。向东走则 x 坐标增加,向北走
则 y 坐标增加;
再接下来 n 行,每行两个数 x_j 和 y_j,表示中转站的坐标。
输出:
输出共一行包含一个数,表示最短的连接管道长度。
输入输出样例
输入:
3
3 5
1 2
4 3
6 3
5 2
2 1
输出:
9
解题思路:
首先,一开始拿到这个题目,哇!暴力大法师(dfs)骗分!真不戳!
哇!一看到数据,很快啊!必超时!那就用贪心骗分吧!5分?!
还是想一想吧……
首先一找规律,就能够发现,其实怎么连根本就不影响到答案?!
因为题目描述中提到过:
那么就只需要在输入的过程中减去天然气井的X和中转站的Y加上天然气井的Y和中转站的X就行了(数组都不用开,我也是fo了)
附上代码:
#include <iostream>
#include <cstdio>
using namespace std;
long long Ans;
int main() {
int N;
scanf ("%d", &N);
for (int i = 1, x, y; i <= N; ++ i)scanf ("%d %d", &x, &y), Ans = Ans - x + y;
for (int i = 1, x, y; i <= N; ++ i)scanf ("%d %d", &x, &y), Ans = Ans + x - y;
printf ("%lld\n", Ans);
}
熄灯强化版
题目描述
现有一排数量为K(4≤K≤25)的灯,其中有些打开,有些关闭。
在此初始配置中,不会出现连续的四个灯(包括四个以上)亮起的情况。
你可以将某些熄灭的灯打开,每当四个或更多连续的灯被打开时,该连续块中的灯将自动关闭。
为了使所有K盏灯都关闭,您需要打开的最少灯数是多少?
输入输出格式
输入:
输入的第一行将由整数K组成,表示灯光的数量。 接下来的K行中的每行将有整数0(表示熄灭的灯)或整数1(表示打开的灯)。
输出:
使得所有等都熄灭的最少操作次数
输入输出样例
输入
5
1
1
0
1
1
输出
1
解题思路
这道题目一眼就能看出是dp,但是dp思路是什么呢?
先将每一个连续的亮着的灯的左右边界求出来(左闭右开方便计算长度)
for循环反着来,F[i]表示的状态是第Total个连续的灯到第i个连续的灯的要全部关掉所需要的最少步数
有两种关法:
1.Itself:自己关,不与其它的连续的灯一起关,步数等于4 - 它本身的长度
2.连续:和别的灯一起关
所以看代码:
#include <iostream>
#include <cstdio>
const int MaxN = 35;
using namespace std;
struct On{
int L,R;
};
On Tot[MaxN];
int Lights[MaxN];
int F[MaxN];
int Total;
int N;
int main() {
scanf ("%d", &N);
for (int i = 1; i <= N; ++ i)scanf ("%d", &Lights[i]);
for (int i = 1, Flag = 0; i <= N + 1; ++ i) {
if (Flag && Lights[i] == 0)Tot[Total].R = i, Flag = 0;
else if (! Flag && Lights[i])Tot[++ Total].L = i, Flag = 1;//找到连续开着的灯的左右端点
}
for (int i = Total, Con; i >= 1; -- i) {
Con = Tot[i].R - Tot[i].L;//Con记录有多少个灯是开着的
F[i] = 4 - Con + F[i + 1];//先初始化为itself
for (int j = i + 1; j <= Total; ++ j) {//和后面的灯一起关
if (Tot[j].R - Tot[i].L >= 8)break ;//>=8是不可能一起关掉的
if (Tot[j].R - Tot[i].L == 7 && Lights[Tot[i].L + 3])break ;
if (Tot[j].R - Tot[i].L == 6 && Lights[Tot[i].L + 2] == 1 && Lights[Tot[i].L + 3] == 1)break ;//这两种情况也是不能够关掉的
Con = Con + Tot[j].R - Tot[j].L;
F[i] = min ((max(4, Tot[j].R - Tot[i].L) - Con + F[j + 1]), F[i]);//打擂台
}
}
printf ("%d\n", F[1]);//F[1]就是答案
}