题目描述

解法

搜索。

代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const char* fin="mahjong.in";
const char* fout="mahjong.out";
const int inf=0x7fffffff;
const int maxn=33,maxa=13;
int i,j,k,l,n,tmp,ans=0,ans1=0,ans2=0;
char s[2];
struct mj{
char d[2];
int cnt,id;
}a[maxn];
int b[256][maxa],r[256][maxa];
int use,times;
int num=0;
char f[14][2];
bool cmp(mj a,mj b){
return a.d[0]<b.d[0] || a.d[0]==b.d[0] && a.d[1]<b.d[1];
}
int next(int v){;
k=v+1;
while (k<n && !a[k].cnt) k++;
return k;
}
void dfs(int v,int want){
int i,j,k;
bool bz=false;
if (v==n){
if (!use || b[use][times]>=tmp){
ans+=tmp;
b[use][times]-=tmp;
}
return;
}
if (a[v].cnt==0) {
dfs(next(v),want);
return ;
}
if (next(v)==-1) return;
j=next(v);
k=next(next(v));
if (a[j].d[0]==a[v].d[0] && a[j].d[1]==a[v].d[1]+1){
if (a[k].d[0]==a[v].d[0] && a[k].d[1]==a[v].d[1]+2) {
a[v].cnt--;
a[j].cnt--;
a[k].cnt--;
dfs(v,want);
a[v].cnt++;
a[j].cnt++;
a[k].cnt++;
}
if (bz) return;
if (want==0){
if (a[v].d[1]>'1' && want==0){
a[v].cnt--;
a[j].cnt--;
tmp=b[a[v].d[0]][a[v].d[1]-1-'0'];
use=a[v].d[0];
times=a[v].d[1]-1-'0';
dfs(v,1);
tmp=0;
a[v].cnt++;
a[j].cnt++;
}
if (bz) return;
if (a[j].d[1]<'9' && want==0){
a[v].cnt--;
a[j].cnt--;
tmp=b[a[j].d[0]][a[j].d[1]+1-'0'];
use=a[v].d[0];
times=a[v].d[1]+1-'0';
dfs(v,1);
tmp=0;
a[v].cnt++;
a[j].cnt++;
}
if (bz) return;
}
}
if (a[j].d[0]==a[v].d[0] && a[j].d[1]==a[v].d[1]+2){
if (want==0){
a[v].cnt--;
a[j].cnt--;
tmp=b[a[j].d[0]][a[j].d[1]-1-'0'];
use=a[v].d[0];
times=a[j].d[1]-1-'0';
dfs(v,1);
tmp=0;
a[v].cnt++;
a[j].cnt++;
}
}
if (bz) return;
if (a[k].d[0]==a[v].d[0] && a[k].d[1]==a[v].d[1]+2){
if (want==0){
a[v].cnt--;
a[k].cnt--;
tmp=b[a[k].d[0]][a[k].d[1]-1-'0'];
use=a[v].d[0];
times=a[k].d[1]-1-'0';
dfs(v,1);
tmp=0;
a[v].cnt++;
a[k].cnt++;
}
}
if (a[v].cnt==2 && want==0){
a[v].cnt-=2;
tmp=b[a[v].d[0]][a[v].d[1]-'0'];
use=a[v].d[0];
times=a[v].d[1]-'0';
dfs(v,1);
tmp=0;
a[v].cnt+=2;
}
if (bz) return;
if (a[v].cnt>=3){
a[v].cnt-=3;
int rans=ans;
dfs(v,want);
//if (rans<ans) bz=true;
a[v].cnt+=3;
}
if (bz) return;
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
n=0;
for (i=0;i<256;i++) for (j=0;j<maxa;j++) b[i][j]=4;
for (i=0;i<14;i++){
scanf("%s",&s);
if (s[1]=='w') b['w'][s[0]-'0']--;
else if (s[1]=='p') b['p'][s[0]-'0']--;
else b['s'][s[0]-'0']--;
swap(s[0],s[1]);
for (j=0;j<n;j++) if (s[0]==a[j].d[0] && s[1]==a[j].d[1]){
a[j].cnt++;
break;
}
if (j==n) {
a[n].id=i;
a[n].cnt=1;
a[n].d[0]=s[0];
a[n++].d[1]=s[1];
}
}
sort(a,a+n,cmp);
a[n].d[0]='0';
a[n].d[1]='0';
a[n].cnt=0;
for (i=0;i<256;i++) for (j=0;j<maxa;j++) r[i][j]=b[i][j];
for (j=0;j<n;j++){
ans=0;
for (k=0;k<256;k++) for (l=0;l<maxa;l++) b[k][l]=r[k][l];
if (a[j].cnt){
a[j].cnt--;
for (i=0;i<n;i++){
if (a[i].cnt>1){
a[i].cnt-=2;
tmp=0;
use=0;
times=0;
dfs(0,0);
a[i].cnt+=2;
}
if (a[i].cnt%3==1){
a[i].cnt-=1;
tmp=b[a[i].d[0]][a[i].d[1]-'0'];
use=a[i].d[0];
times=a[i].d[1]-'0';
dfs(0,1);
a[i].cnt+=1;
}
}
a[j].cnt++;
}
if (ans>ans2 || ans==ans2 && a[j].id<ans1){
ans1=a[j].id;
ans2=ans;
}
}
ans1++;
printf("%d %d",ans1,ans2);
return 0;
}

启发

耗时间的压轴题;

但NOIP喜欢考。

总结两点来优化程序复杂度;

1.首先要把题目所给的信息数据化,并用数据结构存储;

这里所说的数据结构并非高级数据结构,而是类似于桶、链表之类的,有助于搜索编程复杂度优化的合适的数据结构。

2.明确题目所求:在搜索的时候始终贯彻这个目的。

【JZOJ4833】【NOIP2016提高A组集训第3场10.31】Mahjong的更多相关文章

  1. 【NOIP2016提高A组集训第3场10.31】高维宇宙

    题解 分析 因为只有奇数和偶数配对才有可能得出质数, 暴力求出每一对\(a_i+a_j\)为质数,将其中的奇数想偶数连一条边. 二分图匹配,匈牙利算法. #include <cmath> ...

  2. 【JZOJ4831】【NOIP2016提高A组集训第3场10.31】方程式

    题目描述 数据范围 解法 枚举根之后,使用大除法. 代码 #include<stdio.h> #include<iostream> #include<string.h&g ...

  3. 【JZOJ4832】【NOIP2016提高A组集训第3场10.31】高维宇宙

    题目描述 数据范围 解法 由于大于4的素数只有可能由奇数和偶数的和得出. 所以根据数的奇偶性可以分出两类数奇数和偶数. 奇数之间不会相互匹配,偶数之间也不会相互匹配. 那么原问题转化为二分图最大匹配. ...

  4. 【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏

    题目描述 流行的跳棋游戏是在一个有m*n个方格的长方形棋盘上玩的.棋盘起初全部被动物或障碍物占满了.在一个方格中,'X'表示一个障碍物,一个'0'-'9'的个位数字表示一个不同种类的动物,相同的个位数 ...

  5. 【NOIP2016提高A组集训第1场10.29】配对游戏

    题目 流行的跳棋游戏是在一个有mn个方格的长方形棋盘上玩的.棋盘起初全部被动物或障碍物占满了.在一个方格中,'X'表示一个障碍物,一个'0'-'9'的个位数字表示一个不同种类的动物,相同的个位数字表示 ...

  6. 【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_ ...

  7. JZOJ 【NOIP2016提高A组集训第16场11.15】兔子

    JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...

  8. 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 ...

  9. 【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...

随机推荐

  1. non-identifying and identifying

    An identifying relationship means that the child table cannot be uniquely identified without the par ...

  2. Redis 核心

    一.Redis单机多实例原理 每个实例对应不同的配置文件,配置文件对应不同的端口.数据库文件位置.日志位置. 二.Redis单实例多数据库 每个Redis实例都有16个数据库,下标从0-15,当 se ...

  3. 设置mysql二进制日志过期时间

    ((none)) > show variables like 'expire_logs_days'; +------------------+-------+ | Variable_name | ...

  4. poweroj1745: 餐巾计划问题

    传送门 最小费用最大流. 每天拆成两个点,i表示用完的餐巾,i+n表示干净的餐巾. s向i连容量为ri费用为0的边,表示每天用脏的ri条餐巾. i+n向t连容量为ri费用为0的边,表示每天需要用ri条 ...

  5. jdbc原始连接

    public class JdbcInstrt { public static void main(String[] args) { Connection conn = null; PreparedS ...

  6. Spring MVC中获取当前项目的路径

    Spring MVC中获取当前项目的路径 在web.xml中加入以下内容 <!--获取项目路径--> <context-param> <param-name>web ...

  7. mybatis深入理解(七)-----MyBatis缓存机制的设计与实现

    缓存设计 MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存: 一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是 ...

  8. golang redis_example

    main.go package main import ( "fmt" "github.com/garyburd/redigo/redis" ) func ma ...

  9. The web application [ROOT] appears to have started a thread named [spring.cloud.inetutils] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:

    前景提要:启动SpringBoot项目报错 原因: DeliveryPointServiceFallBack上面没有加 @Component-_-!

  10. java-异常进阶-包的使用

    一 finally 1.1 异常执行的顺序 package test; public class Test { public static void main(String[] args) { Dem ...