1. 程式人生 > >洛谷 1736 創意吃魚法

洛谷 1736 創意吃魚法

剪枝 display || ont www http href tro puts

  傳送門

最開始想到的枚舉  

  其實最開始想錯了一些地方,或者說一些地方沒有想清楚。

  現在說一下改完之後的:

  按行和列枚舉點

  第三層循環有兩個 分別是魚的對角線是從左上到右下 和 從左下到右上

  枚舉的點分別是正方形的左上角點和右上角點

  分開來循環只有一個目的:方便剪枝

  舉個栗子:
  4 6
  0 1 0 1 0 0 我們現在枚舉到(1, 2) 這個點
  0 0 1 0 1 0    魚在左上到右下的對角線的情況
  1 1 0 0 0 1    枚舉到正方形邊長到3的時候就發現不行了
  0 1 1 0 1 0    這時直接break 因為邊長為4的情況肯定不行了

  要註意很多細節啊 調了挺久的

技術分享圖片
 1 #include<iostream>
 2 #include<cstdio>
 3 #define go(i,a,b) for(register int i=a;i<=b;i++)
 4 #define M 2510
 5 using namespace std;
 6 int read()
 7 {
 8     int x=0,y=1;char c=getchar();
 9     while(c<0||c>9) {if(c==-) y=-1;c=getchar();}
10     while
(c>=0&&c<=9) {x=(x<<1)+(x<<3)+c-0;c=getchar();} 11 return x*y; 12 } 13 int n,m,ans=1; 14 bool mp[M][M],f1=0; 15 bool ck1(int x,int y,int k) 16 { 17 go(i,x,x+k) go(j,y,y+k) 18 { 19 if(i-x==j-y && !mp[i][j]) return 0; 20 if(i-x!=j-y && mp[i][j]) return
0; 21 } 22 return 1; 23 } 24 bool ck2(int x,int y,int k) 25 { 26 int z=x+y; 27 go(i,x,x+k) go(j,y-k,y) 28 { 29 if(i+j==z && !mp[i][j]) return 0; 30 if(i+j!=z && mp[i][j]) return 0; 31 } 32 return 1; 33 } 34 int main() 35 { 36 n=read();m=read(); 37 go(i,1,n) go(j,1,m) {mp[i][j]=read();if(mp[i][j]) f1=1;} 38 if(!f1) {puts("0");return 0;} 39 go(i,1,n) go(j,1,m) 40 { 41 int maxn=min(n-i+1,m-j+1); 42 go(k,ans+1,maxn) 43 { 44 if(ck1(i,j,k-1)) ans=k; 45 else break ; 46 } 47 maxn=min(n-i+1,j); 48 go(k,ans+1,maxn) 49 { 50 if(ck2(i,j,k-1)) ans=k; 51 else break ; 52 } 53 } 54 printf("%d",ans); 55 return 0; 56 }
枚舉 View Code

  本來以為會TLE幾個點 結果 猝不及防地AC了??

  不過挺慢的 2024ms 開O2 964ms

小結: 在打代碼之前再理一理思路 從頭到尾想一遍(畢竟我總是沒想清楚而錯)

然後又去想 DP:

  感覺好像已經挺明顯的了 明天再寫吧!!

洛谷 1736 創意吃魚法