Dự đoán người đàn ông sẽ đi đâu


17

Một người đàn ông sống ở góc tây bắc (0, 0)của một thị trấn có chiều cao hvà chiều rộng w. Hàng ngày anh đi bộ từ nhà đến biên giới (?, w)hay (h, ?). Trong ví dụ sau, người đàn ông đi đến (3, 3)ngày hôm nay.

(0, 0) +--+  +  +  . (0, 4)
          |         
       +  +--+--+  .
                |   
       +  +  +  +  .
                |   
(3, 0) .  .  .  .  . (3, 4)

Người đàn ông ghi lại một chút tại mỗi điểm ( +ví dụ ở trên). Mỗi khi anh ta đạt đến một điểm, anh ta đi về phía đông nếu bit 1và phía nam khác. Các bit được lật sau khi anh ta rời đi. Ví dụ:

Day 1: 1--0  1  1    Day 2: 0  1  1  1    Day 3: 1--1--1--1--  Day 4: 0  0  0  0  
          |                 |                                         |           
       0  1--0  0           0  0  1  0           1  0  1  0           1--0  1  0  
             |              |                                            |        
       1  0  1--0           1--0  0  1           0  1  0  1           0  1--0  1  
                |              |                                            |     
Destination: (3, 3)  Destination: (3, 1)  Destination: (0, 4)  Destination: (3, 2)

Với kích thước của thị trấn và hồ sơ của người đàn ông, hãy tính điểm đến của người đàn ông sau nhiều nngày.

Đầu vào:

Trong dòng đầu tiên là ba số nguyên h, wn.

Trong các hdòng sau đây là wsố nguyên, biểu thị hồ sơ của người đàn ông.

h <= 1000, w <= 1000, n <= 1000000000

Đầu ra:

Hai số nguyên, biểu thị đích đến của người đàn ông sau nhiều nngày.

Đầu vào mẫu:

3 4 3
1 0 1 1
0 1 0 0
1 0 1 0

Đầu ra mẫu:

0 4

Mã mẫu:

#include <iostream>
using namespace std;
bool d[1000][1000];
int main(){
    int h, w, n;
    cin >> h >> w >> n;
    for(int i = 0; i < h; i++)
        for(int j = 0; j < w; j++)
            cin >> d[i][j];
    int i, j;
    while(n--)
        for(i = 0, j = 0; i < h && j < w;){
            bool &b = d[i][j];
            d[i][j] ? j++ : i++;
            b = !b;
        }
    cout << i << " " << j << endl;
}

Ghi điểm:

  • Số byte thấp nhất trong UTF-8 thắng.
  • Nếu thời gian chạy mã của bạn độc lập n, hãy giảm 50% số điểm của bạn.
    • Đừng chỉ tính kết quả của tất cả 1000000000 ngày hoặc làm bất cứ điều gì tương tự ngu ngốc để nhận phần thưởng này. Tìm một thuật toán hiệu quả!

2 điều tôi không hiểu. Đầu ra, đôi khi bạn sử dụng 0 chỉ số lần khác. Làm thế nào mà làm việc? Có nên giống như đường viền + 1 không? Điều thứ hai là dòng thứ hai với tính điểm. Bạn giải thích điều đó như thế nào?
Teun Pronk

Ngày thứ 4 nên xuất 3,2 phải không?
Teun Pronk

2
Nếu, không có vấn đề gì n, mã của tôi tính kết quả của tất cả 1000000000 ngày, sau đó xuất kết quả n, tôi vẫn nhận được tiền thưởng -50% chứ?
dùng12205

@ace bây giờ bạn đặt nó như thế, nó có ý nghĩa gì không? Cảm ơn vì điều đó: P
Teun Pronk

@TeunPronk Vâng. Đó là lỗi của tôi.
johnchen902

Câu trả lời:


7

GolfScript, 52,5 (105 ký tự với 50% tiền thưởng)

~](;(\((2$(1,*+\@/{]zip 0\{~@@+.2$!+2/\@+.2/\@[\1&]}%zip~@;}%\;[{.0=0=\1${{1>}%}{1>}if.{~}%}do;].1-,n@0-,

Phiên bản này rất hiệu quả và có thể được kiểm tra trực tuyến ngay cả đối với các giá trị lớn.

Nó sử dụng một cách tiếp cận tương tự như giải pháp của user2357112 .


1
Xin đừng yêu cầu một lời giải thích ;-) Tôi thậm chí không thể thay đổi nó mà không phá vỡ và gỡ lỗi con thú này thật kinh khủng.
Howard

13

Python 2, 192 byte * 0,5 tiền thưởng = 96

Để giải quyết vấn đề này một cách hiệu quả, nhận thức chính là chúng ta có thể tính toán số lần mỗi ô được truy cập dựa trên số lần các ô ở trên và bên trái được truy cập mà không cần xác định đường dẫn chính xác được thực hiện. Thực tế, chúng tôi mô phỏng ncác chuyến đi cùng một lúc và theo dõi số lần mỗi ô được sử dụng.

Cải thiện đáng kể do cách tiếp cận dựa trên đẩy lấy cảm hứng từ giải pháp của johnchen902 :

r=lambda:map(int,raw_input().split())
h,w,n=r()
v=[n]+w*[0]
x=y=0
for i in range(h):
 for j,b in enumerate(r()):
    if i-x==j-y==0:d=v[j]&1^b;x+=d;y+=1^d
    f=v[j]+b>>1;v[j]-=f;v[j+1]+=f
print x,y

Trước đây, thực hiện dựa trên kéo:

r=lambda i:map(int,raw_input().split())
h,w,n=r(0)
x=range(h)
g=map(r,x)
v=[w*[0]for i in x]
v[0][0]=n-1
for i in x:
 for j in range(w):v[i][j]+=(i and(v[i-1][j]+(1^g[i-1][j]))/2)+(j and(v[i][j-1]+g[i][j-1])/2)
i=j=0
while i<h and j<w:f=g[i][j]^v[i][j]&1;j+=f;i+=1^f
print i,j

Phiên bản gốc, không có bản quyền:

h, w, n = map(int, raw_input().split())
grid = [map(int, raw_input().split()) for i in xrange(h)]

# Determine the number of times each cell was visited in the first n-1 trips
visits = [[0]*w for i in xrange(h)]
visits[0][0] = n-1
for i in xrange(h):
    for j in xrange(w):
        if i:
            # Count visits from above cell
            visits[i][j] += (visits[i-1][j] + (not grid[i-1][j])) // 2
        if j:
            # Count visits from left cell
            visits[i][j] += (visits[i][j-1] + grid[i][j-1]) // 2

# Flip the bits corresponding to each cell visited an odd number of times
for i in xrange(h):
    for j in xrange(w):
        grid[i][j] ^= visits[i][j] & 1

# Figure out where the final trip ends
i = j = 0
while i < h and j < w:
    if grid[i][j]:
        j += 1
    else:
        i += 1

print i, j

1
Bạn có thể rút ngắn not đến 1^và dài nếu điều kiện có thể được viết f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard

@Howard: Cảm ơn. Chỉnh sửa được áp dụng.
user2357112 hỗ trợ Monica

1
Nếu bạn cho phép rlấy tham số ( r = lambda x: ...), thì bạn có thể rút ngắn g=[r()for i in x]xuống g=map(r,x).
Roberto Bonvallet

@RobertoBonvallet: Yup. Tư vấn thực hiện.
user2357112 hỗ trợ Monica

8

Ruby, 159 143

n,*l=$<.read.split$/
i=->a{a.split.map &:to_i}
x=y=l.map!{|k|i[k]}
(n=i[n])[-1].times{x=y=0
(x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}
p x,y

Dòng đầu tiên sử dụng *toán tử để lấy dòng đầu tiên trong một biến và phần còn lại của đầu vào trong một biến khác. Sau đó, một ichức năng được xác định để chuyển đổi "1 2 3 4"thành [1, 2, 3, 4], được áp dụng cho cả hai ln. ( xyđược lưu lại sau.)

n[-1]là phần tử cuối cùng của n, do đó, khối sau (mô phỏng) được thực thi nhiều lần. Đầu tiên, xyđược khởi tạo về 0 (chúng được khai báo bên ngoài khối sao cho phạm vi của chúng đủ lớn), và sau đó dòng mô phỏng được thực thi, điều này khá tự giải thích, nhưng dù sao đây cũng là một số bình luận:

l[x][y]<1?            is it zero (less than one)?
x+=l[x][y]=1          if it's zero, set it to one, and (conveniently) we can add that to x
:y+=(l[x][y]=0)+1     otherwise, set it to zero, add one, and add that to y
 while x<n[0]&&y<n[1] keep doing this while we're still inside the array

Chỉnh sửa: dòng mô phỏng mới được cung cấp bởi Howard, cảm ơn! Tôi khá chắc chắn rằng tôi hiểu cách thức hoạt động của nó nhưng tôi không có thời gian để thêm một lời giải thích, vì vậy nó sẽ được thêm vào sau.

Cuối cùng, p x,yxuất ra các con số, và chúng ta đã hoàn thành!


Một số chiến thắng cơ bản: thay đổi dòng mới thành $/và vòng lặp while có thể được giảm xuống (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard

4

Delphi XE3 (437 byte | | 897 874 không tính tiền thưởng)

Khi nghĩ về cách giải quyết điều này với phần thưởng tôi đã nghĩ đến những điều sau đây.
Nếu bạn đi bộ 4 ngày, ô 0,0 được thay đổi 4 lần. Tế bào bên phải của nó được thay đổi gấp đôi so với tế bào bên dưới nó.
Nếu có số ngày không đồng đều và số trong ô bắt đầu bằng 1 ô bên phải sẽ nhận được nhiều hơn một ô bên dưới và ngược lại nếu ô bằng 0.

Bằng cách thực hiện điều này cho mọi ô, bạn có thể thấy liệu giá trị cuối có nên được thay đổi hay không: Ô đã được thay đổi X lần. nếu X mod 2> 0 thì thay đổi ô.

Kết quả trong đoạn mã sau:
{Thì thầm tại JohnChen902} tôi có nhận được upvote của bạn bây giờ không? : P

uses SysUtils,Classes,idglobal;var a:TArray<TArray<byte>>;b:TArray<TArray<int64>>;h,w,x,y,t:int16;n:int64;s:string;r:TStringList;tra:byte;begin r:=TStringList.Create;readln(h,w,n);h:=h-1;w:=w-1;for y:=0to h do begin readln(s);r.Add(StringReplace(s,' ','',[rfReplaceAll]));end;SetLength(a,h);SetLength(b,h);for y:=0to h do begin SetLength(a[y],w);SetLength(b[y],w);for x:=1to Length(r[y])do a[y][x-1]:=Ord(r[y][x])-48;end;b[0][0]:=n-1;for Y:=0to h do for X:=0to w do begin t:=b[y][x];if x<w then b[y][x+1]:=b[y][x+1]+iif((t mod 2=1)and(a[y][x]=1),(t div 2)+1,t div 2);if y<h then b[y+1][x]:=b[y+1][x]+iif((b[y][x]mod 2=1)and(a[y][x]=0),(t div 2)+1,t div 2);end;for Y:=0to h do for X:=0to w do if b[y][x]mod 2=1then a[y][x]:=iif(a[y][x]=1,0,1);y:=0;x:=0;repeat a[y][x]:=iif(a[y][x]=1,0,1);if a[y][x]=1then inc(y) else inc(x);until(y>h)or(x>w);write(Format('%d %d',[y,x]));end.

Bị đánh cắp

uses
  SysUtils,Classes,idglobal;
var
  a:TArray<TArray<byte>>;
  b:TArray<TArray<int64>>;
  h,w,x,y,t:int16;
  n:int64;
  s:string;
  r:TStringList;
  tra:byte;
begin
  r:=TStringList.Create;
  readln(h,w,n);
  h:=h-1;w:=w-1;
  for y:=0to h do
  begin
    readln(s);
    r.Add(StringReplace(s,' ','',[rfReplaceAll]));
  end;
  SetLength(a,h);
  SetLength(b,h);
  for y:=0to h do
  begin
    SetLength(a[y],w);
    SetLength(b[y],w);
    for x:=1to Length(r[y])do
      a[y][x-1]:=Ord(r[y][x])-48;
  end;
  b[0][0]:=n-1;
  for Y:=0to h do
    for X:=0to w do
    begin
      t:=b[y][x];
      if x<w then
        b[y][x+1]:=b[y][x+1]+iif((t mod 2=1)and(a[y][x]=1),(t div 2)+1,t div 2);
      if y<h then
        b[y+1][x]:=b[y+1][x]+iif((b[y][x]mod 2=1)and(a[y][x]=0),(t div 2)+1,t div 2);
    end;
  for Y:=0to h do
    for X:=0to w do
      if b[y][x]mod 2=1then
        a[y][x]:=iif(a[y][x]=1,0,1);
  y:=0;x:=0;
  repeat
    a[y][x]:=iif(a[y][x]=1,0,1);
    if a[y][x]=1then
      inc(y)
    else
      inc(x);
  until(y>h)or(x>w);
  write(Format('%d %d',[y,x]));
end.

Bạn chưa nhận được phiếu bầu của tôi. Tôi đã ăn tối. (Được nâng cấp)
johnchen902

4

C ++ 213 byte * 0,5 = 106,5

Đây là giải pháp của tôi. Nó tương tự như giải pháp của user2357112 , nhưng có một số khác biệt:

  • Đầu tiên, tôi gửi thời gian truy cập sang phải và dưới cùng, thay vì tính toán chúng từ trên xuống và bên trái.
  • Thứ hai, tôi làm mọi thứ (đọc đầu vào, điều phối, theo dõi vị trí của người đàn ông) cùng một lúc.
  • Thứ ba, tôi chỉ giữ một hàng bộ nhớ.
#include <iostream>
int o[1001],h,w,r,c,i,j,t,u;int main(){std::cin>>h>>w>>*o;for(;i<h;i++)for(j=0;j<w;)std::cin>>t,u=o[j],o[j]/=2,u%2&&o[j+t]++,r-i|c-j||((u+t)%2?r:c)++,o[++j]+=u/2;std::cout<<r<<" "<<c<<"\n";}

Đây là phiên bản chưa được chỉnh sửa:

#include <iostream>
using namespace std;
int o[1001];
int main(){
    int h, w, n;
    cin >> h >> w >> n;
    o[0] = n;
    int r = 0, c = 0;
    for(int i = 0; i < h; i++)
        for(int j = 0; j < w; j++){
            bool t;
            cin >> t;
            int u = o[j];
            o[j + 1] += u / 2;
            o[j] = u / 2;
            if(u % 2)
                (t ? o[j + 1] : o[j])++;
            if(r == i && c == j)
                ((u + t) % 2 ? r : c)++;
        }
    cout << r << " " << c << endl;
}

Ba sự khác biệt này làm cho mọi thứ khó khăn hơn nhiều. Chúng ta có thể rút ngắn việc lập chỉ mục và kết hợp một số cấu trúc dữ liệu dư thừa. Logic để đẩy các lượt truy cập về phía trước hóa ra ngắn hơn nhiều so với logic để kéo các lượt truy cập từ các ô trước đó. Các điều kiện biên ngang được xử lý đơn giản bằng cách mở rộng cấu trúc dữ liệu thêm một khoảng trắng ở bên phải và các điều kiện biên dọc không phải là vấn đề.
user2357112 hỗ trợ Monica

Tôi đã đưa ra câu trả lời của bạn và kết hợp các khái niệm vào mã của riêng tôi. Cho đến nay, họ đã lấy 84 byte ra khỏi giải pháp của tôi, cải thiện 30%.
user2357112 hỗ trợ Monica

Tôi nghi ngờ bạn có thể lưu một số byte bằng cách không thực hiện --*o;, và thay vào đó chuyển đổi trường hợp nào bạn di chuyển anh chàng xuống và trường hợp nào bạn di chuyển anh chàng sang phải.
user2357112 hỗ trợ Monica

@ user2357112 Đã triển khai, nhưng độ dài mã tăng do lỗi trước đó (Đáng lẽ phải là 218 byte).
johnchen902

3

Python, 177 byte

Lần thử đầu tiên của tôi trong Code Golfing, rất tiếc nếu tôi gặp lỗi ở đây! Mã được sử dụng để lấy đầu vào dựa trên mã của user2357112.

l=lambda:map(int,raw_input().split())
h,w,n=l()
m=[l() for i in[1]*h]
while n>0:
 n-=1;x=y=0
 while x!=w and y!=h:
  if m[y][x]>0:m[y][x]=0;x+=1
  else:m[y][x]=1;y+=1
print y,x

Đầu vào:

3 4 3
1 0 1 1
0 1 0 0
1 0 1 0

Đầu ra:

0 4

2

R, 196 byte * 0,5 = 98

f=function(h,w,n,x){I=J=rep(1,n);for(i in 1:h)for(j in 1:w){M=which(I==i&J==j);N=length(M);if(N){z=seq(1,N,by=2);if(x[i,j])z=-z;f=M[-z];s=M[z];I[f]=i;J[f]=j+1;I[s]=i+1;J[s]=j}};cat(I[n]-1,J[n]-1)}

Ung dung:

f=function(h,w,n,x) {
  I = J = rep(1,n)

  for(i in 1:h) for(j in 1:w) {
    M = which(I==i&J==j)
    N = length(M)
    if (N) {
      z = seq(1,N,by=2)
      if (x[i,j]) z = -z
      f = M[-z]
      s = M[z]
      I[f] = i
      J[f] = j+1
      I[s] = i+1
      J[s] = j
    }
  }
  cat(I[n]-1, J[n]-1)
}

Sử dụng:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.