• 斗地主 && Mayan游戏 && 作业调度方案


    斗地主

    题目描述

    牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的AA到KK加上大小王的共5454张牌来进行的扑克牌游戏。在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2< ext{小王}< ext{大王}3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由 nn 张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。

    现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

    需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:

    本题数据随机,不支持hack,要hack或强力数据请点击这里

    输入输出格式

    输入格式:

    第一行包含用空格隔开的2个正整数 T,nT,n ,表示手牌的组数以及每组手牌的张数。

    接下来 TT 组数据,每组数据 nn 行,每行一个非负整数对 a_i,b_iai,bi ,表示一张牌,其中 a_iai 表示牌的数码, b_ibi表示牌的花色,中间用空格隔开。特别的,我们用 11 来表示数码 AA, 1111 表示数码JJ, 1212 表示数码QQ, 1313 表示数码 KK;黑桃、红心、梅花、方片分别用 1-414 来表示;小王的表示方法为 0101 ,大王的表示方法为 0202 。

    输出格式:

    共 TT 行,每行一个整数,表示打光第 ii 组手牌的最少次数。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 using namespace std;
     10 const int maxn=37;
     11 const int INF=0x7f7f7f7f;
     12 int read(){
     13   int x=0,f=1;char s=getchar();
     14   while(s<'0'||s>'9'){if(s=='-') f=-1;s=getchar();}
     15   while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
     16   return x*f;
     17 }
     18 int t,n,ans;
     19 int req[5]={0,5,3,2};
     20 bool flg1,flg2;
     21 int a[maxn],b[maxn],dp[maxn][maxn][maxn][maxn],cnt[maxn],tot[maxn];
     22 void pre(){
     23   memset(dp,INF,sizeof(dp));
     24   dp[0][0][0][0]=0;
     25   for(int i=0;i<=25;i++){
     26     for(int j=0;j<=25;j++){
     27       for(int k=0;k<=25;k++){
     28         for(int u=0;u<=25;u++){
     29           if(i>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k][u]+1);
     30           if(j>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k][u]+1);
     31           if(k>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j][k-1][u]+1);
     32           if(u>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j][k][u-1]+1);
     33           if(j>0&&u>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k][u-1]+1);
     34           if(j>0&&k>0) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i][j-1][k-1][u]+1);
     35           if(i>0&&u>1) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k][u-2]+1);
     36           if(i>0&&k>1) dp[i][j][k][u]=min(dp[i][j][k][u],dp[i-1][j][k-2][u]+1);
     37         }
     38       }
     39     }
     40   }
     41 }
     42 void san(int stp){
     43   memset(tot,0,sizeof(tot));
     44   for(int i=1;i<=12;i++){
     45     tot[cnt[i]]++;
     46   }tot[cnt[13]]++;
     47   if(flg1==true&&flg2==true){
     48     ans=min(ans,min(dp[tot[4]][tot[3]][tot[2]][tot[1]]+1,dp[tot[4]][tot[3]][tot[2]][tot[1]+2])+stp);
     49   }
     50   else if((flg1==true&&flg2==false)||(flg1==false&&flg2==true)){
     51     ans=min(ans,dp[tot[4]][tot[3]][tot[2]][tot[1]+1]+stp);
     52   }
     53   else{
     54     ans=min(ans,dp[tot[4]][tot[3]][tot[2]][tot[1]]+stp);
     55   }//?
     56   
     57   /*for(int i=1;i<=3;i++){
     58       int tou=1,wei=0;
     59     for(int j=1;j<=12;j++){
     60       if(cnt[j]>=i) wei++;
     61       else{
     62         if(wei-tou+1>=req[i]){
     63           for(int k=tou;k<=wei;k++) cnt[k]-=i;
     64           san(stp+1);
     65           for(int k=tou;k<=wei;k++) cnt[k]+=i; 
     66         }
     67         wei++;tou=wei+1;
     68       }
     69     }
     70     if(tou!=wei&&wei==12&&wei-tou+1>=req[i]){
     71       for(int k=tou;k<=wei;k++) cnt[k]-=i;
     72       san(stp+1);
     73       for(int k=tou;k<=wei;k++) cnt[k]+=i;
     74     }//?
     75   }*/
     76   //有可能是一段连续的,但是从后面截取一段会更优 
     77   int len=0;
     78   for(int i=1;i<=12;i++){
     79     if(cnt[i]<1) len=0;
     80     else{
     81       len++;
     82       if(len>=5){
     83         int tmp=len;
     84         while(tmp>=5){
     85           for(int j=i;j>=i-tmp+1;j--) cnt[j]--;
     86           san(stp+1);
     87           for(int j=i;j>=i-tmp+1;j--) cnt[j]++;
     88           tmp--;
     89         }
     90       }
     91     }
     92   }
     93   len=0;
     94   for(int i=1;i<=12;i++){
     95     if(cnt[i]<2) len=0;
     96     else{
     97       len++;
     98       if(len>=3){
     99         int tmp=len;
    100         while(tmp>=3){
    101           for(int j=i;j>=i-tmp+1;j--) cnt[j]-=2;
    102           san(stp+1);
    103           for(int j=i;j>=i-tmp+1;j--) cnt[j]+=2;
    104           tmp--;
    105         }
    106       }
    107     }
    108   }
    109   len=0;
    110   for(int i=1;i<=12;i++){
    111     if(cnt[i]<3) len=0;
    112     else{
    113       len++;
    114       if(len>=2){
    115         int tmp=len;
    116         while(tmp>=2){
    117           for(int j=i;j>=i-tmp+1;j--) cnt[j]-=3;
    118           san(stp+1);
    119           for(int j=i;j>=i-tmp+1;j--) cnt[j]+=3;
    120           tmp--;
    121         }
    122       }
    123     }
    124   }
    125 }
    126 int main(){
    127   t=read();n=read();
    128   pre();
    129   while(t--){
    130       memset(a,0,sizeof(a));memset(b,0,sizeof(b));
    131       memset(cnt,0,sizeof(cnt));memset(tot,0,sizeof(tot));
    132       flg1=false;flg2=false;ans=INF;
    133     for(int i=1;i<=n;i++){
    134       a[i]=read();b[i]=read();
    135       if(a[i]>=3) a[i]-=2;
    136       else if(a[i]>=1&&a[i]<=2) a[i]+=11; 
    137       else if(a[i]==0){
    138         if(b[i]==1) {a[i]=14;flg1=true;}
    139         if(b[i]==2) {a[i]=15;flg2=true;}
    140       }//注意第二个要打else 
    141       cnt[a[i]]++;
    142     }
    143     san(0);
    144     printf("%d
    ",ans);
    145   }
    146   return 0;
    147 } 

     Mayan游戏

    题目描述

    Mayan puzzle是最近流行起来的一个游戏。游戏界面是一个77 行 imes 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:

    1 、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见输入输出样例说明中的图66到图77 );如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);

    2 、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。

    注意:

    a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图44 ,三个颜色为11 的方块和三个颜色为 22 的方块会同时被消除,最后剩下一个颜色为22的方块)。

    b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。

    3 、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。

    上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。

    输入输出格式

    输入格式:

    共 6 行。

    第一行为一个正整数n,表示要求游戏通关的步数。

    接下来的5行,描述7×5 的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1开始顺序编号,相同数字表示相同颜色)。

    输入数据保证初始棋盘中没有可以消除的方块。

    输出格式:

    如果有解决方案,输出n行,每行包含 3 个整数x,y,g,表示一次移动,每两个整数之间用一个空格隔开,其中(x ,y)表示要移动的方块的坐标,g 表示移动的方向,1 表示向右移动,-11表示向左移动。注意:多组解时,按照xx为第一关健字,yy为第二关健字,11优先于-11 ,给出一组字典序最小的解。游戏界面左下角的坐标为(0 ,0)

    如果没有解决方案,输出一行,包含一个整数-1

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 using namespace std;
      7 const int maxn=17;
      8 int n;
      9 int mp[maxn][maxn],bef[maxn][maxn][maxn],tp[maxn];
     10 bool qu[maxn][maxn],fih;
     11 struct Ans{
     12   int x,y,f;
     13 }ans[maxn];
     14 void cpy(int stp){
     15   for(int i=0;i<5;i++)
     16     for(int j=0;j<7;j++)
     17       bef[stp][i][j]=mp[i][j];
     18 }
     19 void update(){
     20   for(int i=0;i<5;i++){
     21     int num=0;
     22     for(int j=0;j<7;j++){
     23       if(!mp[i][j]) num++;
     24       else if(num!=0){
     25           mp[i][j-num]=mp[i][j];mp[i][j]=0;
     26       }
     27     }
     28   }
     29 }
     30 bool clr(){
     31   memset(qu,false,sizeof(qu));bool flag=false;
     32   for(int i=0;i<5;i++){
     33     for(int j=0;j<7;j++){
     34       if(i-1>=0&&i+1<5){
     35         if(mp[i][j]&&mp[i-1][j]==mp[i][j]&&mp[i+1][j]==mp[i][j]){
     36           qu[i][j]=true;qu[i+1][j]=true;qu[i-1][j]=true;flag=true;
     37         }
     38       }
     39       if(j-1>=0&&j+1<7){
     40         if(mp[i][j]&&mp[i][j-1]==mp[i][j]&&mp[i][j+1]==mp[i][j]){
     41           qu[i][j]=true;qu[i][j-1]=true;qu[i][j+1]=true;flag=true;
     42         }
     43       }
     44     }
     45   }
     46   if(!flag) return false;
     47   for(int i=0;i<5;i++)
     48     for(int j=0;j<7;j++)
     49       if(qu[i][j]) mp[i][j]=0;
     50   return true;
     51 }
     52 void move(int x,int y,int f){
     53   int tmp=mp[x][y];
     54   mp[x][y]=mp[x+f][y];mp[x+f][y]=tmp;
     55   update();
     56   while(clr()) update();
     57 }
     58 bool check(){
     59   for(int i=0;i<5;i++)
     60     for(int j=0;j<7;j++)
     61       if(mp[i][j]) return false;
     62   return true;
     63 }
     64 void dfs(int stp){
     65   if(check()){
     66     for(int i=0;i<stp;i++){
     67       cout<<ans[i].x<<" "<<ans[i].y<<" "<<ans[i].f<<endl; 
     68     }
     69     fih=true;
     70   }
     71   if(stp>=n) return;
     72   cpy(stp);
     73   for(int i=0;i<5;i++){
     74     for(int j=0;j<7;j++){
     75       if(!mp[i][j]) continue;
     76       if(i+1<5&&mp[i+1][j]!=mp[i][j]){
     77         move(i,j,1);
     78         ans[stp]=(Ans){i,j,1};
     79         dfs(stp+1);if(fih) return;
     80         ans[stp]=(Ans){0,0,0};
     81         for(int i=0;i<5;i++)
     82           for(int j=0;j<7;j++)
     83             mp[i][j]=bef[stp][i][j];
     84       }
     85       if(i-1>=0&&mp[i-1][j]==0){
     86         move(i,j,-1);
     87         ans[stp]=(Ans){i,j,-1};
     88         dfs(stp+1);if(fih) return;
     89         ans[stp]=(Ans){0,0,0};
     90         for(int i=0;i<5;i++)
     91           for(int j=0;j<7;j++)
     92             mp[i][j]=bef[stp][i][j];
     93       }
     94     }
     95   }
     96 }
     97 int main(){
     98   cin>>n;
     99   for(int i=0;i<5;i++){
    100       cin>>mp[i][tp[i]];
    101     while(mp[i][tp[i]]!=0){
    102       tp[i]++;cin>>mp[i][tp[i]];
    103     }
    104   }
    105   dfs(0);
    106   if(ans[0].f==0) cout<<-1<<endl;
    107   return 0;
    108 }

    考试的时候要有文件输入输出,所以不能直接exit(0)要回溯的时候进行判断

    这个qu数组真的很妙,巧妙地解决了超过3个连续喝交叉连续的问题

    以后的模拟题争取自己做出来

    做模拟题要有想法

    作业调度方案

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=27;
     8 const int maxm=1e6+7;
     9 int n,m,ans;
    10 int en_gong[maxn],en_ji[maxn],num[maxn],ji[maxn][maxn],shi[maxn][maxn],a[maxn*maxn];
    11 bool yong[maxn][maxm];
    12 int main(){
    13   //freopen("a.in","r",stdin);
    14   cin>>m>>n;
    15   for(int i=1;i<=n*m;i++) cin>>a[i];
    16   for(int i=1;i<=n;i++)
    17     for(int j=1;j<=m;j++)
    18       cin>>ji[i][j];
    19   for(int i=1;i<=n;i++)
    20     for(int j=1;j<=m;j++)
    21       cin>>shi[i][j];
    22   for(int i=1;i<=n*m;i++){
    23     int JI=ji[a[i]][++num[a[i]]];
    24     int SHI=shi[a[i]][num[a[i]]];
    25     bool flag,reach=false;;
    26     for(int j=en_gong[a[i]]+1;j<=en_ji[JI];j++){
    27       flag=true;
    28       for(int k=j;k<j+SHI;k++){
    29         if(yong[JI][k]){
    30           flag=false;break;
    31         }
    32       }
    33       if(flag){
    34         for(int k=j;k<j+SHI;k++) yong[JI][k]=true;
    35         en_gong[a[i]]=j+SHI-1;reach=true;break;
    36       }
    37     }
    38     if(!reach){
    39       int st=max(en_ji[JI]+1,en_gong[a[i]]+1);
    40       for(int j=st;j<st+SHI;j++) yong[JI][j]=true;
    41       en_gong[a[i]]=st+SHI-1;en_ji[JI]=st+SHI-1;
    42     }
    43   }
    44   for(int i=1;i<=m;i++) ans=max(ans,en_ji[i]);
    45   cout<<ans<<endl;
    46 }
  • 相关阅读:
    bzoj3224 普通平衡树
    bzoj 1067 分情况讨论
    bzoj 1269 bzoj 1507 Splay处理文本信息
    bzoj 2733 Splay 启发式合并,名次树
    bzoj1502 simpson求面积
    b_lq_晚会界面单(线段树维护区间最大值表+预留m个位置)
    a_lc_统计子树中城市之间最大距离(枚举子集 + floyd / 2*dfs 求直径)
    b_lq_城市建设 & 公路修建水题 & 新的开始(虚拟结点+MST)
    b_lg_无线通讯网 & 北极通讯网络(问题转化+kruskal)
    b_lg_搭配购买(并查集+01背包)
  • 原文地址:https://www.cnblogs.com/lcan/p/9878664.html
Copyright © 2020-2023  润新知