【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏
题目描述
流行的跳棋游戏是在一个有m*n个方格的长方形棋盘上玩的。棋盘起初全部被动物或障碍物占满了。在一个方格中,‘X’表示一个障碍物,一个‘0’~‘9’的个位数字表示一个不同种类的动物,相同的个位数字表示相同种类的动物。一对动物只有当它们属于同一种类时才可以被消去。消去之后,他们所占的方格就成为空方格,直到游戏结束。要消去一对动物的前提条件是:这对候选动物所在的方格必须相邻,或它们之间存在一条通路。棋盘上一个方格只和其上下左右的方格相邻。一条通路是由一串相邻的空方格组成。路的长度则是通路中空方格的数目。你要输出可被消去的动物的最多对数,以及在此操作过程中,最小的通路长度总和。
数据范围
N,M<=5
解法
暴力+剪枝
正确性可以保证,时间效率较低;
可以考虑牺牲点正确性以提高时间效率。
A*
正确性和时间效率取决于估价函数。
带策略的暴力
正确性勉强,时间效率卡常数;
贪心
正确性无法保证,时间效率高;
所以可以考虑牺牲时间效率,多次求解求最优。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const char* fin="pair.in";
const char* fout="pair.out";
const int inf=0x7fffffff;
const int maxn=13,maxm=maxn*maxn;
const int h[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int n,m,i,j,k,maxx,ans1,ans2,interesting=5,hx,hy,ans3,ans4;
char a[maxn][maxn];
bool bz[maxn][maxn];
int b[maxm][2],head,tail,c[6];
int f[maxn][maxn];
int heavy(int x,int y){
return max(abs(x-hx),abs(y-hy));
}
void add(int x,int y,int z,int awful){
if (z>=f[x][y] || (!bz[x][y] && awful==0) || a[x][y]=='X') return ;
b[++tail][0]=x;
b[tail][1]=y;
f[x][y]=z;
}
int getdis(int x,int y,int u,int v){
int i,j,k,ans=inf;
memset(f,127,sizeof(f));
head=tail=0;
add(x,y,0,1);
while (head++<tail){
for (i=0;i<4;i++){
j=b[head][0]+h[i][0];
k=b[head][1]+h[i][1];
if (j>0 && j<=n && k>0 && k<=m)
if (j==u && k==v) ans=min(f[b[head][0]][b[head][1]],ans);
else add(j,k,f[b[head][0]][b[head][1]]+1,0);
}
}
return ans;
}
void work(int x,int y){
int i,j,k,minx=10000,mnid[2],mminx=inf;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
if (!bz[i][j] && a[i][j]==a[x][y]){
if (x==i && y==j) continue;
k=getdis(x,y,i,j);
if (k<minx || k==minx && heavy(i,j)<mminx){
minx=k;
mminx=heavy(i,j);
mnid[0]=i;
mnid[1]=j;
}
}
if (minx==10000) return;
else{
/*ans1++;
ans2+=minx;
bz[x][y]=true;
bz[mnid[0]][mnid[1]]=true;*/
if (c[1]>minx){
c[1]=minx;
c[2]=x;
c[3]=y;
c[4]=mnid[0];
c[5]=mnid[1];
}
}
}
void solve(int v){
int i,j,k;
while (1){
c[1]=10000;
for (i=v;i<=n-v+1;i++) if (!bz[i][m-v+1] && a[i][m-v+1]!='X') work(i,m-v+1);
for (i=m-v+1;i>=v;i--) if (!bz[i][v] && a[i][v]!='X') work(i,v);
for (i=v;i<=n-v+1;i++) if (!bz[n-v+1][i] && a[n-v+1][i]!='X') work(n-v+1,i);
for (i=m-v+1;i>=v;i--) if (!bz[v][i] && a[v][i]!='X') work(v,i);
if (c[1]<10000){
bz[c[2]][c[3]]=true;
bz[c[4]][c[5]]=true;
ans1++;
ans2+=c[1];
}else break;
}
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%s",a[i]+1);
maxx=min((n+1)/2,(m+1)/2);
for (hx=1;hx<=n;hx++)
for (hy=1;hy<=m;hy++){
memset(bz,0,sizeof(bz));
ans1=ans2=0;
for (i=1;i<=maxx;i++){
for (j=i;j;j--){
solve(j);
}
}
if (ans1>ans3 || ans1==ans3 && ans2<ans4){
ans3=ans1;
ans4=ans2;
}
}
for (hx=1;hx<=n;hx++)
for (hy=1;hy<=m;hy++){
memset(bz,0,sizeof(bz));
ans1=ans2=0;
for (i=maxx;i;i--){
for (j=i;j;j--){
solve(j);
}
}
if (ans1>ans3 || ans1==ans3 && ans2<ans4){
ans3=ans1;
ans4=ans2;
}
}
for (hx=1;hx<=n;hx++)
for (hy=1;hy<=m;hy++){
memset(bz,0,sizeof(bz));
ans1=ans2=0;
for (i=maxx;i;i--){
for (j=1;j<=maxx;j++){
solve(j);
}
}
if (ans1>ans3 || ans1==ans3 && ans2<ans4){
ans3=ans1;
ans4=ans2;
}
}
for (hx=1;hx<=n;hx++)
for (hy=1;hy<=m;hy++){
memset(bz,0,sizeof(bz));
ans1=ans2=0;
for (i=1;i<=maxx;i++){
for (j=i;j;j--){
solve(j);
}
}
if (ans1>ans3 || ans1==ans3 && ans2<ans4){
ans3=ans1;
ans4=ans2;
}
}
printf("%d %d",ans3,ans4);
return 0;
}
启发
这种题常出现在NOIP提高组的压轴题,
往往没有稳定复杂度的算法。
此时就要考虑上述几种做法,进行取舍,以骗得最高的分数。
大致上就是平衡时间效率和正确性。
此外还有考虑编程复杂度的问题,以我的观点:
贪心的编程复杂度最简单,也最容易调试;
因为贪心的每一次操作具有后效性。
【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏的更多相关文章
- 【NOIP2016提高A组集训第1场10.29】配对游戏
题目 流行的跳棋游戏是在一个有mn个方格的长方形棋盘上玩的.棋盘起初全部被动物或障碍物占满了.在一个方格中,'X'表示一个障碍物,一个'0'-'9'的个位数字表示一个不同种类的动物,相同的个位数字表示 ...
- 【NOIP2016提高A组集训第1场10.29】完美标号
题目 给定M个二元组(A_i, B_i),求X_1, ..., X_N满足:对于任意(A_i, B_i),有|X_{A_i} - X_{B_i}| = 1成立. 分析 显然,对于二元组(x,y),X_ ...
- 【NOIP2016提高A组集训第3场10.31】高维宇宙
题解 分析 因为只有奇数和偶数配对才有可能得出质数, 暴力求出每一对\(a_i+a_j\)为质数,将其中的奇数想偶数连一条边. 二分图匹配,匈牙利算法. #include <cmath> ...
- 【JZOJ4831】【NOIP2016提高A组集训第3场10.31】方程式
题目描述 数据范围 解法 枚举根之后,使用大除法. 代码 #include<stdio.h> #include<iostream> #include<string.h&g ...
- 【JZOJ4832】【NOIP2016提高A组集训第3场10.31】高维宇宙
题目描述 数据范围 解法 由于大于4的素数只有可能由奇数和偶数的和得出. 所以根据数的奇偶性可以分出两类数奇数和偶数. 奇数之间不会相互匹配,偶数之间也不会相互匹配. 那么原问题转化为二分图最大匹配. ...
- 【JZOJ4833】【NOIP2016提高A组集训第3场10.31】Mahjong
题目描述 解法 搜索. 代码 #include<stdio.h> #include<iostream> #include<string.h> #include< ...
- JZOJ 【NOIP2016提高A组集训第16场11.15】兔子
JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...
- JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线
JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...
随机推荐
- Linux中如何安装mysql数据库
安装mysql 1.解压源码压缩包 如果服务器可以上网也可以采用在线安装方式,在线安装操作简单具体见下面在线安装步骤 进入源码压缩包所在目录输入#tar -zxvf mysql-5.6.17-linu ...
- python-pygame安装教程
网上有很多关于python,pygame的安装教程.大都比较麻烦,下面为大家介绍一种非常简单的安装方法.(因为安装大都是新手教程写详细一些) python是32位 python是3.6 1 pip配置 ...
- 【Java爬虫】爬取南通大学教务处成绩
没使用自动登录,所以获取是比较麻烦.. 1.http://jwgl.ntu.edu.cn/cjcx 进入官网,进行账号密码登录 2.点击全部成绩查询(也一定要点进去,不然cookie不会返回值) ...
- TZOJ 4021 Ugly Problem(线段树区间子段最大)
描述 给定一个序列A[0],A[1],…A[N-1],要求找到p0,p1,p2,p3使得A[p0]+A[p0+1]+…+A[p1] + A[p2]+A[p2+1]+…+A[p3]最大(0<=p0 ...
- Leetcode216. Combination Sum III组合总数3
找出所有相加之和为 n 的 k 个数的组合.组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字. 说明: 所有数字都是正整数. 解集不能包含重复的组合. 示例 1: 输入: k = ...
- leetcode 352 & leetcode 239 & leetcode 295 & leetcode 53 & leetcode 209
lc352 Data Stream as Disjoint Intervals 可以用treemap解 key保存interval的start,value保存interval的end.分别找出当前va ...
- localStorage对象简单应用 - - 访问次数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 读书笔记--Head First 面向对象分析与设计 目录
1.良好应用程序的基石 2.收集需求 3.需求变更 4.分析 5.良好的设计=灵活的软件 6.解决大问题 7.架构 8.设计原则 9.迭代与测试 10.OOA&D 的生命周期 附录1 附录2
- Excel 表格中根据某一列的值从另一个xls文件的对应sheet中查找包含其中一列的内容(有点拗口)
=VLOOKUP(C3&"*",INDIRECT("'[2008-2016年三地商务明细表.xls]"&L3&"年北京'!$D ...
- E浏览器常见的9个css Bug以及解决办法
我们在浏览网页的时候经常看见这样的现象:某个网页在IE6浏览器中打开很正常,但是在IE8里面打开可能完全变形了.或者也有可能出现完全相反的现象.这让Web程序员及设计师往往为了其CSS在各个IE版本下 ...