Hướng dẫn giải của IOI07 Miners


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

uses math;
const fi='';
      oo=1000000000;
var f:array[0..1,0..3,0..3,0..3,0..3] of longint;
    g:array[0..3,0..3,0..3] of longint;
    h:array[1..10,0..1] of longint;
    e:array[0..3] of longint;
    n,i,z,re,a,b,c,d,x,p,q:longint;
    ch:char;

procedure rset(z:longint);
var a,b,c,d:longint;
begin
     for a:=0 to 3 do
         for b:=0 to 3 do
           for c:=0 to 3 do
             for d:=0 to 3 do
                 f[z,a,b,c,d]:=-oo;
     c:=0;
     for a:=1 to 3 do
       for b:=1 to 3 do
       begin
            inc(c);
            h[c,0]:=a;
            h[c,1]:=b;
       end;
     h[10,0]:=0; h[10,1]:=0;
end;

function calc(a,b,c:longint):longint;
var i,r:longint;
begin
     r:=0;
     for i:=1 to 3 do e[i]:=0;
     inc(e[a]); inc(e[b]); inc(e[c]);
     for i:=1 to 3 do
         if e[i]>0 then inc(r);
     calc:=r;
end;

begin
     assign(input,fi); reset(input);
     readln(n);
     rset(0); rset(1);
     f[0,0,0,0,0]:=0;
     for a:=0 to 3 do
         for b:=0 to 3 do
             for c:=0 to 3 do
                 g[a,b,c]:=calc(a,b,c);
     for i:=1 to n do
     begin
          z:=i and 1;
          read(ch);
          case ch of
            'M':x:=1;
            'F':x:=2;
            else x:=3;
          end;
          for p:=1 to 10 do
           for q:=1 to 10 do
            if (p<>10) or (q<>10) or (i=1) then
            begin
                 a:=h[p,0]; b:=h[p,1];
                 c:=h[q,0]; d:=h[q,1];
                 if p+q=20 then
                 begin
                      f[z,0,0,x,x]:=1;
                      f[z,x,x,0,0]:=1;
                 end
                 else
                 begin
                      if p=10 then
                      begin
                           f[z,x,x,c,d]:=max(f[z,x,x,c,d],f[1-z,0,0,c,d]+1);
                           f[z,0,0,d,x]:=max(f[z,0,0,d,x],f[1-z,0,0,c,d]+g[c,d,x]);
                      end
                      else
                      begin
                           if q=10 then
                           begin
                                f[z,a,b,x,x]:=max(f[z,a,b,x,x],f[1-z,a,b,0,0]+1);
                                f[z,b,x,0,0]:=max(f[z,b,x,0,0],f[1-z,a,b,0,0]+g[a,b,x]);
                           end
                           else
                           begin
                                f[z,b,x,c,d]:=max(f[z,b,x,c,d],f[1-z,a,b,c,d]+g[a,b,x]);
                                f[z,a,b,d,x]:=max(f[z,a,b,d,x],f[1-z,a,b,c,d]+g[c,d,x]);
                           end;
                      end;
                 end;
            end;
     end;
     re:=n;
     for a:=0 to 3 do
       for b:=0 to 3 do
         for c:=0 to 3 do
           for d:=0 to 3 do
             re:=max(re,f[z,a,b,c,d]);
     writeln(re);
     close(input);
end.

Code mẫu của happyboy99x

#include<iostream>
#include<cstring>
using namespace std;

const int N = 100000;
int f[N + 1][4][4][4][4];

int numDistinct(int x, int y, int z) {
    if(x == 3) return y == 3 || y == z ? 1 : 2;
    if(y == 3) return 1;
    if(x != y && x != z && y != z) return 3;
    if(x == y && x == z) return 1;
    return 2;
}

void checkMax(int &x, int y) {
    if(x < y) x = y;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("NKMINERS.inp", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    int n;
    string s;
    cin >> n >> s;
    memset(f, 0xc1, sizeof f);
    int res = 0;
    f[0][3][3][3][3] = 0;
    for(int i = 0; i <= n; ++i) {
        int type = i == n ? -1 : s[i] == 'M' ? 0 : s[i] == 'F' ? 1 : 2;
        for(int x1 = 0; x1 < 4; ++x1) {
            for(int y1 = 0; y1 < 4; ++y1) {
                for(int x2 = 0; x2 < 4; ++x2) {
                    for(int y2 = 0; y2 < 4; ++y2) {
                        if(f[i][x1][y1][x2][y2] >= 0) {
                            if(i < n) {
                                checkMax(f[i + 1][y1][type][x2][y2], f[i][x1][y1][x2][y2] + numDistinct(x1, y1, type));
                                checkMax(f[i + 1][x1][y1][y2][type], f[i][x1][y1][x2][y2] + numDistinct(x2, y2, type));
                            } else {
                                checkMax(res, f[i][x1][y1][x2][y2]);
                            }
                        }
                    }
                }
            }
        }
    }
    cout << res << '\n';
    return 0;
}

Code mẫu của ladpro98

#include <cstdio>
const int N = 100005;
using namespace std;
int F[2][4][4][4][4];
int val[4][4][4];
int a[N];
int n, res;

void maximize(int& x, int y) {
    if (x < y) {
        x = y; if (res < x) res = x;
    }
}

int main()
{
    scanf("%d\n", &n);
    int i, j, k, x1, y1, x2, y2; char c;
    for(i=1; i<=n; i++) {
        scanf("%c", &c);
        if (c == 'M') a[i] = 1;
        if (c == 'F') a[i] = 2;
        if (c == 'B') a[i] = 3;
    }
    for(i=0; i<=3; i++) for(j=0; j<=3; j++) for(k=0; k<=3; k++) {
        if (i == 1 || j == 1 || k == 1) val[i][j][k]++;
        if (i == 2 || j == 2 || k == 2) val[i][j][k]++;
        if (i == 3 || j == 3 || k == 3) val[i][j][k]++;
    }
    int now = 0, next = 1, p, prev;
    F[now][0][a[1]][0][0] = F[now][0][0][0][a[1]] = 1;
    for(i=1; i<n; i++) {
        for(x1=0; x1<=3; x1++)
        for(y1=(x1 != 0 ? 1 : 0); y1<=3; y1++)
        for(x2=0; x2<=3; x2++)
        for(y2=(x2 != 0 ? 1 : 0); y2<=3; y2++) {
            p = a[i + 1]; prev = F[now][x1][y1][x2][y2];
            if (prev == 0) continue;
            maximize(F[next][y1][p][x2][y2], prev + val[x1][y1][p]);
            maximize(F[next][x1][y1][y2][p], prev + val[x2][y2][p]);
        }
        next ^= 1; now ^= 1;
    }
    printf("%d", res);
    return 0;
}

Code mẫu của RR

#include <iostream>
#include <algorithm>

#define FOR(i,a,b)  for(int i=a; i<=b; i++)
#define FORD(i,a,b) for(int i=a; i>=b; i--)
#define MAXN 100111
using namespace std;

int n,a[MAXN],f[2][4][4][4][4],cnt[4][4][4];
char s[MAXN];

void inp() {
    scanf("%d\n",&n);
    gets(s);
    FOR(i,1,n)
        if (s[i-1]=='M') a[i]=0;
        else if (s[i-1]=='F') a[i]=1;
        else a[i]=2;
}

void solve() {
    FOR(x,0,3)
    FOR(y,0,3)
    FOR(z,0,3)
        FOR(t,0,2)
            if (x==t || y==t || z==t) cnt[x][y][z]++;

    memset(f,-1,sizeof f);
    f[0][3][3][3][3]=0;
    int now=0;
    FOR(i,0,n-1) {
        int u=a[i+1];
        now=1-now;
        FOR(a1,0,3)
        FOR(a2,0,3)
        FOR(b1,0,3)
        FOR(b2,0,3)
            if (f[1-now][a1][a2][b1][b2]>=0) {
                f[now][a2][u][b1][b2] >?= f[1-now][a1][a2][b1][b2]+cnt[a1][a2][u];
                f[now][a1][a2][b2][u] >?= f[1-now][a1][a2][b1][b2]+cnt[b1][b2][u];
            }
    }

    int res=0;
    FOR(a1,0,3)
    FOR(a2,0,3)
    FOR(b1,0,3)
    FOR(b2,0,3)
        res >?= f[now][a1][a2][b1][b2];

    printf("%d\n",res);
}

int main() {
    inp();
    solve();
    return 0;
}

Code mẫu của hieult

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cassert>
#include<ctime>
#include<algorithm>
#include<iterator>
#include<iostream>
#include<cctype>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<list>
//#include<conio.h>
#define ep 0.000000001
#define maxn 10011
#define oo 1111111111
#define base 100000000
#define TR(c, it) for(typeof((c).begin()) it=(c).begin(); it!=(c).end(); it++)
double const PI=4*atan(1);

using namespace std;

typedef pair<int, int> II;
typedef vector<int> VI;
typedef vector<II> VII;
typedef vector<VI> VVI;
typedef vector<VII> VVII;

int f[100111][13][13],n,A;
char s[100111];
//VVI::iterator it;

int khac (int a1,int a2,int a3){
      if(a1==0) return (a2!=a3)+1; 
      if(a1==a2 && a2==a3)
          return 1;
      if(a1==a2 && a1!=a3) return 2;
      if(a1==a3 && a1!=a2) return 2;
      if(a2==a3 && a1!=a2) return 2;
      return 3;
}

int main(){
    // freopen("NKMINERS.in","r",stdin);
      scanf("%d",&n);
      scanf("%s",s);
      memset(f,-1,sizeof(f));
      f[0][0][0] = 0;
      for(int ii = 1 ;ii<=n;ii++){
            if(s[ii-1]=='M') A = 1;
            if(s[ii-1]=='B') A = 2;
            if(s[ii-1]=='F') A = 3;
            for(int i = 0;i<13;i++){
                 for(int j = 0;j<=3;j++){
                      if(j==0){
                            if(f[ii-1][0][i]!=-1) f[ii][A][i] = f[ii-1][0][i]+1;
                            if(f[ii-1][i][0]!=-1) f[ii][i][A] = f[ii-1][i][0]+1;
                      }
                      else{
                            for(int k = 0;k<=3;k++){
                                 if(f[ii-1][k*3+j][i]!=-1)  f[ii][j*3+A][i] >?= f[ii-1][k*3+j][i]+khac(k,j,A);
                                 if(f[ii-1][i][k*3+j]!=-1)  f[ii][i][j*3+A] >?= f[ii-1][i][k*3+j]+khac(k,j,A);
                            }
                      }
                 }
            }    
      }
      int KQ = 0;
      for(int i = 0;i<13;i++)
           for(int j = 0;j<13;j++)
               KQ >?= f[n][i][j];
      printf("%d",KQ);
     // getch();
}

Code mẫu của ll931110

{$MODE DELPHI,R+,Q+,H+}
program NKMINERS;
const
  input  = '';
  output = '';
  maxv = 100000 * 100;
  maxk = 9;
  link: array[0..9,1..3] of integer = ((1,2,3),(1,4,5),(6,2,7),(8,9,3),
                                       (6,2,7),(8,9,3),(1,4,5),(8,9,3),
                                       (1,4,5),(6,2,7));
  cost: array[0..9,1..3] of integer = ((1,1,1),(1,2,2),(2,1,2),(2,2,1),
                                       (2,2,3),(2,3,2),(2,2,3),(3,2,2),
                                       (2,3,2),(3,2,2));
  //state: 0[0],1[1],2[2],3[3],12[4],13[5],21[6],23[7],31[8],32[9]
var
  cur,next: array[0..maxk,0..maxk] of integer;
  n,res: integer;
  s: string;

procedure init;
var
  f: text;
begin
  assign(f, input);
    reset(f);

  readln(f, n);
  readln(f, s);

  close(f);
end;

procedure solve;
var
  i,j,t,ek,ds,dc: integer;
  ch: char;
begin
  for i := 0  to maxk do
    for j := 0 to maxk do cur[i,j] := -maxv;
  cur[0,0] := 0;
  next := cur;

  for t := 1 to n do
    begin
      ch := s[t];
      case ch of
        'M': ek := 1;
        'F': ek := 2;
        'B': ek := 3;
      end;

      for i := 0 to maxk do
        for j := 0 to maxk do
          begin
            ds := link[i,ek];
            dc := cost[i,ek];
            if next[ds,j] < cur[i,j] + dc then next[ds,j] := cur[i,j] + dc;

            ds := link[j,ek];
            dc := cost[j,ek];
            if next[i,ds] < cur[i,j] + dc then next[i,ds] := cur[i,j] + dc;
          end;

      cur := next;
    end;

  res := 0;
  for i := 0 to maxk do
    for j := 0 to maxk do
      if res < cur[i,j] then res := cur[i,j];
end;

procedure printresult;
var
  f: text;
begin
  assign(f, output);
    rewrite(f);
    writeln(f, res);
  close(f);
end;

begin
  init;
  solve;
  printresult;
end.

Code mẫu của skyvn97

#include<cstdio>
#include<cstring>
#define MAX   100100
#define FOR(i,a,b) for (int i=(a);i<=(b);i=i+1)
#define REP(i,n) for (int i=0;i<(n);i=i+1)
#define maximize(x,y) if (x<(y)) x=(y)
#define ok
int n;
char s[MAX];
int f[MAX][4][4][4][4];
inline int count(int x,int y,int z) {
    bool ex[7];
    memset(ex,false,sizeof ex);
    ex[x]=true;
    ex[y]=true;
    ex[z]=true;
    int ret=0;
    FOR(i,1,3) if (ex[i]) ret++;
    return (ret);
}
void init(void) {
    scanf("%d",&n);
    scanf("%s",s+1);
    FOR(i,1,n) {
        if (s[i]=='M') s[i]=1;
        if (s[i]=='F') s[i]=2;
        if (s[i]=='B') s[i]=3;
    }
}
void optimize(void) {
    f[1][0][s[1]][0][0]=1;
    f[1][0][0][0][s[1]]=1;  
    FOR(i,1,n-1) REP(p11,4) REP(p12,4) REP(p21,4) REP(p22,4)
        if (f[i][p11][p12][p21][p22]>0) {
            maximize(f[i+1][p12][s[i+1]][p21][p22],f[i][p11][p12][p21][p22]+count(p11,p12,s[i+1]));
            maximize(f[i+1][p11][p12][p22][s[i+1]],f[i][p11][p12][p21][p22]+count(p21,p22,s[i+1]));
        }
    int res=0;
    FOR(p11,1,3) REP(p11,4) REP(p12,4) REP(p21,4) REP(p22,4)
        maximize(res,f[n][p11][p12][p21][p22]);
    printf("%d",res);
}
int main(void) {
    init();
    optimize();
    return 0;
}

Code mẫu của khuc_tuan

#include <iostream>
#include <cstdio>

using namespace std;

int n;
char a[100010];
int f[4][4][4][4], g[4][4][4][4];

int main() {

    scanf("%d", &n);
    gets(a);
    gets(a);

    memset( f, -1, sizeof(f));
    f[3][3][3][3] = 0;

    for(int i=0;i<n;++i) {
        memset( g, -1, sizeof(g));
        int next = 0;
        if(a[i]=='M') next = 1;
        if(a[i]=='F') next = 2;
        for(int i00=0;i00<4;++i00) for(int i01=0;i01<4;++i01) {
            for(int i10=0;i10<4;++i10) for(int i11=0;i11<4;++i11) if(f[i00][i01][i10][i11]!=-1) {
                // cho mo 1
                int tmp = 1 + f[i00][i01][i10][i11];
                if(i01!=3 && i01!=next) ++tmp;
                if(i00!=3 && i00!=i01 && i00!=next) ++tmp;
                int &gg = g[i01][next][i10][i11];
                if(gg<tmp) gg = tmp;
                // cho mo 2
                tmp = 1 + f[i00][i01][i10][i11];
                if(i11!=3 && i11!=next) ++tmp;
                if(i10!=3 && i10!=i11 && i10!=next) ++tmp;
                int &g2 = g[i00][i01][i11][next];
                if(g2<tmp) g2 = tmp;
            }
        }
        memmove( f, g, sizeof(f));
    }
    int result = 0;
    for(int i00=0;i00<4;++i00) for(int i01=0;i01<4;++i01) 
            for(int i10=0;i10<4;++i10) for(int i11=0;i11<4;++i11) if(f[i00][i01][i10][i11]!=-1)
                result >?= f[i00][i01][i10][i11];
    cout << result << endl;
    //system("pause");
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.