2019.10.6 题解报告
2019.10.6 题解报告
时间安排:
-
T1: 2:00~2:50 T2: 2:50~4:00 T3: 4:00~4:50
- 一直推 T1的 样例 , 但是脑子抽了忽略了某些情况 导致 怀疑样例有误
经过 长时间的努力 最后决定先打后两个题的暴力 - T2 欧拉路秒了 , 写炸了没过
- T3 神仙DP 决定状压60
- 最后10分钟 对各代码进行了微调
- 一直推 T1的 样例 , 但是脑子抽了忽略了某些情况 导致 怀疑样例有误
答题情况:
- T1: 0 T2:0 T3:60
题目解析:
T1:
二分答案 + 模拟
二分答案 枚举 最后一艘船 到达的时间
在 check 函数中 ,
由于 队首 的船 不会被之前的船阻挡 ,
则 先计算出 队首 的船最后到达的位置
然后 从尾到首 枚举每一艘船
计算 此船 在没有阻挡情况下 能到达的 最远距离
与 前一艘船 最后到达的位置 + 前一艘船的船长 位置 进行比较
很显然 , 如果被阻挡 ,
那么 前一艘船 最后到达的位置 + 前一艘船的船长 位置 距离终点较远
否则 在没有阻挡情况下 能到达的 最远距离 较远
取距离终点 较远 的 作为 此船 最后到达的位置
T2:
题目要求:
求得 图中 有多少条 欧拉通路 , 并且 输出 每一条的路径
-
直接 求欧拉通路 比较麻烦
可以将题目转化为 求 欧拉回路 -
首先对于 一笔画问题 , 有一性质:
对于 图中每一个点 , 如果 其度数为奇数, 则称为 奇点
否则 称为 偶点对于 图中每一个联通块 ,
- 当奇点数 = 0 或 奇点数 = 2时 , 可以一笔画成
- 否则 , 需要的 笔数 = 奇点数/2 (下取整)
-
那么 可以对图进行 重新构造:
将奇点之间 两两连虚边 ,
代表 两奇点之间 联通 需要 画新的一笔 -
之后 检查对每一个 奇点:
如果此奇点 没有 被作为 dfs的起点 , 那么进行dfs
dfs中 从每一个点 经过 没有被经过的 边 向其他点进行转移
每个起点 至多转移一次 , 当不能转移时进行回溯回溯时检查 经过的 边
如果 是实边 , 那么 加入 最新一笔 的 经过路径中
否则 , 说明 又添加了一笔 , ans++ , 新开一条路径手玩多组样例后 发现 ,
对 奇点dfs时 会多经过一条 虚边
则 回溯完成后 , ans-- -
之后 检查每一个偶点
按照上述 dfs规则 进行转移 与 更新答案
但是 回溯完成后 ans不变
最后输出即可
T3:
60%数据:
简单状压DP , 对 出现的 基站 编号进行状压 ,
转移时 枚举 不存在于 某状态的 基站编号 ,
并计算出 将其加入 的 代价
取 全集的 最小代价 即可
100%数据 :
-
首先 只考虑 一行的状态:
可以发现 , 如果 先放中间 后放两边 ,
那么 将一行 填满的 代价
一定 不比 先放两边 后放中间 差于是 只有一行的情况 变成了一个 区间DP问题
即每次都可以 取最左侧 或 最右侧 的元素
求最小价值
类似 NOIp中的 矩阵取数游戏 -
然后 将上述结论扩展到 二维矩阵
类比上述问题 , 可以设 f[i][j][k][l] 为:
左上角 (i,j) --> 右下角(k,l) 子矩阵中 , 所有基站建设完毕的最小代价使用记忆化dfs进行转移
对于每一个子矩阵 , 暴力计算 子矩阵贡献 并转移即可
代码实现:
T1:
- 考场代码:
#include<cstdio>
#include<cstring>
#include<ctype.h>
#define max(a,b) a>b?a:b
const int MARX = 1e5+10;
const double fabs = 1e-6;
//=============================================================
int T,n , l[MARX],x[MARX],v[MARX];
//=============================================================
inline int read()
{
int s=1, w=0; char ch=getchar();
for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
return s*w;
}
bool check(double time)
{
double last_boat = -1e15;
for(int i=n; i>=0; i--)
{
double boati = 1.0*x[i]-(v[i]*1.0)*time;
last_boat = max(boati,last_boat+1.0*l[i-1]);
if(last_boat >0.00) return 0;
}
return 1;
}
//=============================================================
signed main()
{
// freopen("cruise.in","r",stdin);
// freopen("cruise.out","w",stdout);
T=read();
while(T--)
{
memset(l,0,sizeof(l));
memset(x,0,sizeof(x));
memset(v,0,sizeof(v));
n=read();
for(int i=0; i<=n; i++) l[i] = read();
for(int i=0; i<=n; i++) x[i] = read();
for(int i=0; i<=n; i++) v[i] = read();
double ans=0;
check(3.5);
for(double le=0,ri=1e9; ri-le>=fabs; )
{
double mid = (le+ri)/2;
if(check(mid)) ans = mid,ri=mid;
else le=mid;
}
printf("%.3lf\n",ans);
}
}
- 正解:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 +5;
struct edge{
double v,s,len;
}es[maxn];
int main()
{
freopen("cruise.in","r",stdin);
freopen("cruise.out","w",stdout);
int n,test;
scanf("%d",&test);
while(test--)
{
int m = 1;
scanf("%d", &n);
for(int i = 1;i <= n + 1;i++) scanf("%lf",&es[i].len);
for(int i = 1;i <= n + 1;i++) scanf("%lf",&es[i].s);
for(int i = 1;i <= n + 1;i++) scanf("%lf",&es[i].v);
double ans = 0;
double lazy = 0;
for(int i = 1;i <= n + 1;i++)
{
if(i != 1) lazy += es[i].len;
double t = (es[i].s + lazy) / es[i].v;
ans = max(t,ans);
}
printf("%.10f\n",ans);
}
return 0;
}
T2:
- 考场代码:
//
/*
By:Luckyblock
*/
#include<cstdio>
#include<vector>
#include<cstring>
#include<ctype.h>
const int MARX = 1e5+10;
//=============================================================
struct edge
{
int u,v,ne,data,use;
}e[MARX<<1];
int T,n,m,num,ans , head[MARX];
int mod2is1,mod2is0,mod2is1_u,outedge[MARX];
std::vector <int> road[MARX];
//=============================================================
inline int read()
{
int s=1, w=0; char ch=getchar();
for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
return s*w;
}
void add(int u,int v,int data)
{
e[++num].ne=head[u],head[u]=num;
data = ((num%2?data:-data));
e[num].u=u,e[num].v=v,e[num].data=data;
outedge[u]++;
}
void graph_build()
{
n=read(),m=read();
for(int i=1; i<=m ;i++)
{
int u=read(),v=read();
add(u,v,i), add(v,u,i);
}
for(int i=1; i<=n; i++)
{
mod2is1 += (outedge[i]%2),
mod2is0 += (!(outedge[i]%2));
mod2is1_u = (outedge[i]%2?i:mod2is1_u);
}
}
void dfs(int u)
{
for(int i=head[u]; i; i=e[i].ne)
if(!e[i].use)
{
e[i].use=1, e[(i%2==1?i+1:i-1)].use=1;
outedge[e[i].u]--, outedge[e[i].v]--;
road[ans].push_back(e[i].data);
dfs(e[i].v);
return;
}
}
//=============================================================
signed main()
{
// freopen("travelling.in","r",stdin);
// freopen("travelling.out","w",stdout);
T=read();
while(T--)
{
memset(e,0,sizeof(e));
memset(outedge,0,sizeof(outedge));
memset(head,0,sizeof(head));
for(int i=0; i<=n; i++) road[i].clear();
num = ans = 0;
mod2is1 = mod2is0 = 0;
graph_build();
if(mod2is1 == 0) dfs(1);
if(mod2is1 == 2) dfs(mod2is1_u);
if(mod2is1 !=0 && mod2is1 !=2)
for(int i=1; i<=n; i++)
if(outedge[i] %2)
{
for(int j=head[i]; j; j=e[j].ne)
if(!e[j].use)
{
e[j].use=1, e[(j%2==1?j+1:j-1)].use=1;
outedge[e[j].u]--, outedge[e[j].v]--;
road[ans].push_back(e[j].data);
dfs(e[j].v);
ans++;
}
}
printf("%d\n",ans);
for(int i=0; i<(ans==0?1:ans); putchar('\n'),i++)
{
printf("%d ",road[i].size());
for(int j=0,size = road[i].size(); j<size; j++)
printf("%d ",road[i][j]);
}
}
}
/*
10
4 4
1 2
1 3
2 3
4 1
8 8
1 2
2 3
3 4
4 5
5 2
5 6
6 7
6 8
2 1
1 2
*/
- 正解:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn =1e5+5;
struct Edge{
int to,id,next;
bool f;
}edges[maxn<<4];
int tot,head[maxn],cnt;
bool vis[maxn];
vector<int> res[maxn];
int deg[maxn];
void init()
{
tot=0;
cnt=0;
memset(deg,0,sizeof(deg));
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v ,int id)
{
edges[tot].f = 0;edges[tot].to=v;edges[tot].id = id;edges[tot].next =head[u];
head[u]=tot++;
}
void dfs(int u)
{
vis[u]=true;
//cout<<u<<" in "<<cnt<<endl;
for(int i=head[u];~i;i=edges[i].next){
int v =edges[i].to,id =edges[i].id;
if(!edges[i].f){
edges[i].f = edges[i^1].f = true;
dfs(v);
if(id) res[cnt].push_back(-id);
else cnt++;
//cout<<u<<" out "<<cnt<<endl;
}
}
}
void Print()
{
printf("%d\n",cnt-1);
for(int i=1;i<=cnt;++i){
printf("%d",res[i].size());
int k = res[i].size();
for(int j=0;j<k;++j) printf(" %d",res[i][j]);
printf("\n");
res[i].clear();
}
}
int main()
{
freopen("travelling.in","r",stdin);
freopen("travelling.out","w",stdout);
int T,N,M,u,v,tmp;
scanf("%d", &T);
while(T--){
scanf("%d%d",&N,&M);
init();
for(int i=1;i<=M;++i){
scanf("%d%d",&u,&v);
deg[u]++,deg[v]++;
AddEdge(u,v,i);
AddEdge(v,u,-i);
}
u=0;
for(int i=1;i<=N;++i){
if(deg[i]&1){
if(u){
AddEdge(u,i,0);
AddEdge(i,u,0);
u=0;
}
else u=i;
}
}
for(int i=1;i<=N;++i){
if(!vis[i] && (deg[i]&1)){
cnt++;
dfs(i);
cnt--;
}
}
for(int i=1;i<=N;++i){
if(!vis[i] && deg[i]){
cnt++;
dfs(i);
}
}
Print();
}
return 0;
}
T3:
- 考场代码:
#include<cstdio>
#include<cstring>
#include<ctype.h>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
const int MARX = 1<<21;
//=============================================================
int num,all ,x[70],y[70],f[MARX];
char tmp[10] = "9";
//=============================================================
int abs(int x) {return (x<0?-x:x);}
void DP()
{
memset(f,63,sizeof(f)); f[0] = 0;
for(int i=0; i<=all; i++)
for(int j=0; j<=num; j++)
if(!((1<<j) & i))
{
int add = 0;
for(int k=0; k<=num; k++)
if((1<<k) & i)
{
int tx = abs(x[j]-x[k]) , ty = abs(y[j]-y[k]);
add = max(add, max(tx,ty));
}
f[i+(1<<j)] = min(f[i+(1<<j)],f[i]+add);
}
}
//=============================================================
signed main()
{
freopen("station.in","r",stdin);
freopen("station.out","w",stdout);
for(int i=1; i<=8; i++)
{
scanf("%s",tmp+1);
for(int j=1; j<=8; j++)
if(tmp[j]=='#') x[num]=i,y[num++]=j;
}
num--; all = (1<<(num+1))-1;
DP();
printf("%d",f[all]);
}
/*
........
........
...#....
.#......
.......#
........
........
........
#...#..#
#..#....
...##...
.#......
#..#...#
#..#..#.
...#..#.
#..#..#.
*/
- 正解:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int oo = 1000000000;
char a[10][10];
int f[10][10][10][10];
int calc(int x1, int y1, int x2, int y2, int i1, int j1, int i2, int j2)
{
int res = 0;
for (int i = i1; i <= i2; ++ i)
for (int j = j1; j <= j2; ++ j)
if (a[i][j] == '#')
res += max(max(abs(i-x1), abs(i-x2)), max(abs(j-y1), abs(j-y2)));
return res;
}
int dp(int x1, int y1, int x2, int y2)
{
if (x1 > x2 || y1 > y2) return 0;
int &res = f[x1][y1][x2][y2];
if (res > -1) return res;
res = calc(x1, y1, x2, y2, x1, y1, x1, y2) + dp(x1+1, y1, x2, y2);
res = min(res, calc(x1, y1, x2, y2, x2, y1, x2, y2) + dp(x1, y1, x2-1, y2));
res = min(res, calc(x1, y1, x2, y2, x1, y1, x2, y1) + dp(x1, y1+1, x2, y2));
res = min(res, calc(x1, y1, x2, y2, x1, y2, x2, y2) + dp(x1, y1, x2, y2-1));
return res;
}
int main()
{
freopen("station.in", "r", stdin);
freopen("station.out", "w", stdout);
for (int i = 1; i <= 8; ++ i)
scanf("%s", a[i] + 1);
memset(f, -1, sizeof(f));
printf("%d\n", dp(1, 1, 8, 8));
return 0;
}