考的是NOIP2017day1原題,html
開始看到小凱的疑惑時感受特水,由於這題初中老師講過,node
很nice的秒切ios
T2發現是個大模擬,雖然字符串不太會用,但起碼題意很好理解數組
邊打代碼邊敲註釋,差點變量名不夠用ide
就這樣一個半小時過去了,手捏的樣例也過了spa
覺得100pts,就放了過去看T3設計
T3考的是最短路計數,想了想之前好像沒有寫過這類題,3d
硬着頭皮寫了個dfs暴力統計道路數,爲防止跑不出來還加了個計數器特判code
指望能在無0環樣例中騙點分,htm
後來在luogu上全WA了
運用了小學奧數的芝士
(賽後據說有根據昨天T2作法騙了60分的,但那個必會MLE,不過在考場上能夠用來打表找規律)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 long long a, b;//十年OI一場空,不開long long見祖宗 5 int main() 6 { 7 //freopen("math.in","r",stdin); 8 //freopen("math.out","w",stdout); 9 cin>>a>>b; 10 cout<<(a*b-a-b)<<endl; 11 return 0; 12 }
這雖然是個大模擬,但坑點太多了啊
發現給出的程序格式單一,那麼直接用cin單獨接收就好
用flag標記小明給出的複雜度中有無n,用cst和fcst分別接收常數級的複雜度和指數級的複雜度(後來發現cst只多是1
爲了區分fsct是1的狀況,把cst賦成-1
接着讀入每一個串,把F,和E兩種狀況分開處理
單獨開個char數組存變量的名字,讀一個F就加一個,讀一個E就減一個(注意加以前先判斷有沒有重複的
接收起始量和終止量
開兩個標記標記是不是n,開兩個int記錄兩個量的大小
開個xh記錄循環到的第幾層
若是先後都是n,不做處理
考慮到有的循環能直接退出,開個spl標記
開一個棧存儲有n的循環層的層數
若是前面只有前面是n,或者前面大於後面而且spl == 0 時間複雜度與top取最大值,並用spl記錄此時層數
若是隻有後面是n,向棧里加一個元素,大小爲此時的層數,時間複雜度與top取最大值
若是層數小於棧頂的層數,就將其彈出
若是有層數小於0或者變量名重複的狀況打個標記最後輸出REE便可
在E操做中,若是層數小於spl,要記得歸0
詳細過程看代碼
1 //T2不會是個大模擬吧 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<string> 6 #include<cmath> 7 using namespace std; 8 int T, n, cnt, Otime, xh, xh2;//cnt變量名計數 9 int cst, fcst;//cst:常數級,fcst:指數級 10 bool err = 0, flag;//標記複雜度是指數級仍是常數級 11 char blm[110];//存變量名 12 string s1, s2; //讀入的程序 13 int spl;//一個特殊標記,標記外層循環o1,內層循環on^m的狀況 14 int stk[110], top = 0; 15 16 void worke(){ 17 cnt--; xh--; 18 if(xh <= spl) spl = 0; 19 if(xh < 0) err = 1; 20 if(xh < stk[top]) top--; 21 return ; 22 } 23 24 void workf(){ 25 bool str_n = 0, ed_n = 0;//標記起始點是否爲n,標記終止點是否爲n ; 26 int str = 0, ed = 0; 27 string bl, qsl, zzl;//變量, 起始量, 終止量 28 cin>>bl>>qsl>>zzl; 29 xh++;//循環層數加一 30 for(int i = 1; i <= cnt; ++i) 31 if(blm[i] == bl[0]) { 32 err = 1; return ; 33 } 34 //存變量 35 //處理起始點 36 if(qsl[0] == 'n') str_n = true; 37 else { 38 for(int i = 0; i < qsl.size(); ++i){ 39 str = str * 10 + qsl[i] - '0'; 40 } 41 } 42 //處理終止點 43 if(zzl[0] == 'n') ed_n = true; 44 else { 45 for(int i = 0; i < zzl.size(); ++i){ 46 ed = ed * 10 + zzl[i] - '0'; 47 } 48 } 49 if(str_n && ed_n) return ; 50 blm[++cnt] = bl[0]; 51 52 if(((str_n && !ed_n) || (!str_n && !ed_n && str > ed)) && !spl) Otime = max(Otime, top), spl = xh; 53 if(!str_n && ed_n && !spl) { 54 stk[++top] = xh; 55 Otime = max(Otime, top); 56 } 57 if(xh < stk[top]) top--; 58 return ; 59 } 60 61 int main() 62 { 63 //freopen("complexity.in","r",stdin); 64 //freopen("complexity.out","w",stdout); 65 scanf("%d", &T); 66 while(T--){ 67 scanf("%d", &n); 68 cnt = cst = fcst = xh = xh2 = top = 0; 69 flag = 0, err = 0; 70 Otime = -1; 71 cin>>s1; 72 // cout<<n<<"zsf"<<endl; 73 int len = s1.size(); 74 for(int i = 0; i < len; ++i){ 75 if(s1[i] == 'n'){ 76 flag = true; 77 } 78 if(s1[i] >= '0' && s1[i] <= '9'){//記錄複雜度 79 if(flag) fcst = fcst * 10 + s1[i] - '0'; 80 else cst = -1; 81 } 82 } 83 for(int i = 1; i <= n; ++i){ 84 cin>>s2; 85 if(s2[0] == 'F') workf(); 86 else worke(); 87 // cout<<spl<<"zsf"<<xh<<" "<<top<<endl; 88 } 89 if(err || xh) printf("ERR\n"); 90 else{ 91 if(!flag){ 92 if(Otime == cst) printf("Yes\n"); 93 else printf("No\n"); 94 } 95 else{ 96 if(Otime == fcst) printf("Yes\n"); 97 else printf("No\n"); 98 } 99 } 100 // cout<<"lkp"<<Otime<<" "<<cst<<" "<<fcst<<endl; 101 } 102 return 0; 103 }
關鍵是0環的問題不太好處理,但正解好像設計到一點dp,0環直接被過濾掉了
https://www.cnblogs.com/wxyww/p/noip2017Day1T3.html#643448942
這個博客講的挺好的
題解是SPFA,我用的dij作的(題目中只有0環,嘿嘿,能卡過去)
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 const int MAXN = 1e5+5; 7 const int MAXM = 2e5+5; 8 struct edge{ 9 int to, w, nxt; 10 }e[MAXM], e2[MAXM]; 11 struct node{ 12 int point, dis; 13 bool operator < (const node &b) const {return dis > b.dis; } 14 }; 15 int head[MAXN], num_edge, head2[MAXN], num_edge2; 16 int T, n, m, k ,p, lim, cnt, ans; 17 int dis[MAXN], num[MAXN]; 18 bool vis[MAXN]; 19 priority_queue<node> q; 20 21 int read(){ 22 int s = 0, w = 1; 23 char ch = getchar(); 24 while(ch < '0' || ch > '9') {if(ch == '-') w = -1; ch = getchar(); } 25 while(ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + ch - '0', ch = getchar(); 26 return s * w; 27 } 28 29 void add(int from, int to, int w){ 30 e[++num_edge].to = to; 31 e[num_edge].w = w; 32 e[num_edge].nxt = head[from]; 33 head[from] = num_edge; 34 } 35 36 void add2(int from, int to, int w){ 37 e2[++num_edge2].to = to; 38 e2[num_edge2].w = w; 39 e2[num_edge2].nxt = head2[from]; 40 head2[from] = num_edge2; 41 } 42 43 44 void dij(){ 45 memset(dis, 0x3f, sizeof(dis)); 46 memset(vis, 0, sizeof(vis)); 47 dis[n] = 0; 48 q.push((node){n, 0}); 49 while(!q.empty()){ 50 node t = q.top(); q.pop(); 51 int u = t.point; 52 vis[u] = 1; 53 for(int i = head2[u]; i; i = e2[i].nxt){ 54 int v = e2[i].to; 55 if(dis[v] > dis[u] + e2[i].w){ 56 dis[v] = dis[u] + e2[i].w; 57 if(!vis[v]) q.push((node){v, dis[v]}); 58 } 59 } 60 } 61 } 62 63 int bz[MAXN][60], f[MAXN][60]; 64 int dfs(int x, int lim){ 65 if(bz[x][lim] == 2) return f[x][lim]; 66 if(bz[x][lim] == 1) return -1; 67 bz[x][lim] = 1; 68 for(int i = head[x]; i; i = e[i].nxt){ 69 int v = e[i].to; 70 int w = lim - (dis[v] + e[i].w - dis[x]); 71 if(w < 0 || w > k) continue; 72 int ans = dfs(v, w); 73 if(ans == -1) return -1; 74 f[x][lim] += ans; 75 f[x][lim] %= p; 76 } 77 bz[x][lim] = 2; 78 return f[x][lim]; 79 } 80 81 int main() 82 { 83 //freopen("park.in","r",stdin); 84 //freopen("park.out","w",stdout); 85 T = read(); 86 while(T--){ 87 memset(head, 0, sizeof(head)); 88 memset(head2, 0, sizeof(head2)); 89 memset(f, 0, sizeof(f)); 90 memset(bz, 0, sizeof(bz)); 91 num_edge = num_edge2 = cnt = 0; 92 n = read(), m = read(), k = read(), p = read(); 93 for(int i = 1, u, v, w; i <= m; ++i){ 94 u = read(), v = read(), w = read(); 95 add(u, v, w); 96 add2(v, u, w); 97 } 98 dij(); 99 f[n][0] = 1; 100 for(int i = 0; i <= k; ++i){ 101 int kkk = dfs(1, i); 102 if(kkk == -1){ 103 cnt = -1; break; 104 } 105 cnt += kkk; 106 cnt %= p; 107 } 108 printf("%d\n", cnt); 109 } 110 return 0; 111 }