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: 0 T2:0 T3:60

题目解析:

T1:

二分答案 + 模拟
二分答案 枚举 最后一艘船 到达的时间

在 check 函数中 ,
由于 队首 的船 不会被之前的船阻挡 ,
则 先计算出 队首 的船最后到达的位置

然后 从尾到首 枚举每一艘船
计算 此船 在没有阻挡情况下 能到达的 最远距离
与 前一艘船 最后到达的位置 + 前一艘船的船长 位置 进行比较

很显然 , 如果被阻挡 ,
那么 前一艘船 最后到达的位置 + 前一艘船的船长 位置 距离终点较远
否则 在没有阻挡情况下 能到达的 最远距离 较远

取距离终点 较远 的 作为 此船 最后到达的位置


T2:

题目要求:
求得 图中 有多少条 欧拉通路 , 并且 输出 每一条的路径

  • 直接 求欧拉通路 比较麻烦
    可以将题目转化为 求 欧拉回路

  • 首先对于 一笔画问题 , 有一性质:
    对于 图中每一个点 , 如果 其度数为奇数, 则称为 奇点
    否则 称为 偶点

    对于 图中每一个联通块 ,

    1. 当奇点数 = 0 或 奇点数 = 2时 , 可以一笔画成
    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;
}
posted @ 2019-10-06 16:47  Luckyblock  阅读(142)  评论(0编辑  收藏  举报