CF2B The least round way 題解
阿新 • • 發佈:2018-11-30
都是淚呀。。。↑
題目傳送門
題意(直接複製了QWQ)
題目描述
給定由非負整陣列成的\(n \times n\)的正方形矩陣,你需要尋找一條路徑:
以左上角為起點,
每次只能向右或向下走,
以右下角為終點 並且,如果我們把沿路遇到的數進行相乘,積應當是最小“round”,換句話說,應當以最小數目的0的結尾.
輸入格式
第一行包含一個整數 \((2 \leq n \leq 1000)\),\(n\)為矩陣的規模,接下來的\(n\)行包含矩陣的元素(不超過\(10^9\)的非負整數).
輸出格式
第一行應包含最小尾0的個數,第二行打印出相應的路徑(譯註:D為下,R為右)
思路
樓下其實說得蠻清楚了,我主要就是說一下坑。。。
構成末尾是0的只能是\(2^a\)
坑
TLE的小朋友們看這裡啦。。。
TLE的小朋友們看這裡啦。。。
TLE的小朋友們看這裡啦。。。
(重要的事情說三遍)
此題特別會卡時。
比如說一開始預處理每個數是\(2^a\)與\(2^b\)時,需要將此數不間斷地除下去,為什麼呢?因為卡常數。。。也許時我RP的原因吧。。。卡了半天,終於卡過去了。。。
具體詳見程式碼:
程式碼
(我知道你要看這個)
#include<bits/stdc++.h> using namespace std;//奇醜無比的碼風 int n,a[1010][1010],f[2][1010][1010],dp[2][1010][1010]; int ans,qx,qy; bool ff; inline int get2(register int x,register int y){ if(a[x][y]==0){return 0;} //特判 register int pt=0; while(a[x][y]%2==0) ++pt,a[x][y]/=2; //卡常數 return pt; } inline int get5(register int x,register int y){ if(a[x][y]==0){return 0;} //特判 register int pt=0; while(a[x][y]%5==0) ++pt,a[x][y]/=5; //卡常數 return pt; } inline void print(register int k,register int x,register int y,register int first){ if(x==1&&y==1) ; else if(x==1) print(k,x,y-1,0); else if(y==1) print(k,x-1,y,1); else if(dp[k][x][y]==dp[k][x-1][y]+f[k][x][y]) print(k,x-1,y,1); else print(k,x,y-1,0); if(first==6666) return ; putchar(first==0?'R':'D'); //一開始在n,n點時不需要輸出 return ; } int main(){ while(cin>>n){ ff=0;qx=0;qy=0; for(register int i=1;i<=n;i++){ for(register int j=1;j<=n;j++){ cin>>a[i][j]; if(a[i][j]==0){ qx=i;qy=j; ff=1; } } } for(register int i=1;i<=n;i++){ for(register int j=1;j<=n;j++){ f[0][i][j]=get2(i,j); f[1][i][j]=get5(i,j); } } memset(dp,63,sizeof(dp)); for(register int i=1;i<=n;i++) for(register int j=1;j<=n;j++){ dp[0][i][j]=min(dp[0][i][j],dp[0][i-1][j]); dp[0][i][j]=min(dp[0][i][j],dp[0][i][j-1]);//從左格子與上格子中取最小值 if(i==1&&j==1) dp[0][i][j]=0; dp[0][i][j]+=f[0][i][j]; } for(register int i=1;i<=n;i++) for(register int j=1;j<=n;j++){ dp[1][i][j]=min(dp[1][i][j],dp[1][i-1][j]); dp[1][i][j]=min(dp[1][i][j],dp[1][i][j-1]);//從左格子與上格子中取最小值 if(i==1&&j==1) dp[1][i][j]=0; dp[1][i][j]+=f[1][i][j]; } ans=min(dp[0][n][n],dp[1][n][n]);//初步ans if(ans>1&&ff==1){ //特判有0的情況,如果有0,那麼答案只有0或1. putchar('1'); putchar('\n'); for(register int i=1;i<qx;i++) putchar('D'); for(register int i=1;i<qy;i++) putchar('R'); for(register int i=qx;i<n;i++) putchar('D'); for(register int i=qy;i<n;i++) putchar('R'); putchar('\n'); }else{ cout<<ans; putchar('\n'); if(dp[0][n][n]<dp[1][n][n]) print(0,n,n,6666); //分2、5討論 else print(1,n,n,6666); putchar('\n'); } } return 0; }