洛谷 1736 創意吃魚法
阿新 • • 發佈:2019-01-28
剪枝 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枚舉 View Code(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]) return0; 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 }
本來以為會TLE幾個點 結果 猝不及防地AC了??
不過挺慢的 2024ms 開O2 964ms
小結: 在打代碼之前再理一理思路 從頭到尾想一遍(畢竟我總是沒想清楚而錯)
然後又去想 DP:
感覺好像已經挺明顯的了 明天再寫吧!!
洛谷 1736 創意吃魚法