CodeVs天梯黃金Gold題解

      網友投稿 677 2025-04-03

      title: CodeVs天梯之Gold

      date: 2017-12-28

      tags:

      天梯

      CodesVs

      categories: OI

      CodeVs天梯之Gold

      2018.01.04 By gwj233

      均分紙牌

      #include using namespace std; const int maxn = 110; int a[maxn], sum, ans; int main(){ int n; cin>>n; for(int i = 1; i <= n; i++){ cin>>a[i]; sum += a[i]; } sum /= n; for(int i = 1; i <= n; i++){ if(a[i] != sum){ ans++; a[i+1] -= sum-a[i]; } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      線段覆蓋

      #include #include using namespace std; const int maxn = 110; int a[maxn], b[maxn], c[maxn]; bool cmp(int x, int y){ return b[x]==b[y] ? a[x]>n; for(int i = 1; i <= n; i++){ int x, y; cin>>x>>y; //輸入有坑,可能先大再小 a[i]=min(x,y); b[i]=max(x,y); c[i]=i; } sort(c+1,c+n+1,cmp); int t = -999, ans = 0; for(int i = 1; i <= n; i++){ if(t <= a[c[i]]){ t = b[c[i]]; ans++; } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      高精度練習之減法

      #include #include #include using namespace std; const int maxn = 510; int a[maxn], b[maxn], c[maxn]; int main(){ string s1, s2; cin>>s1>>s2; if(s1.size()1 && c[c[0]]==0)c[0]--; for(int i = c[0]; i >= 1; i--)cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      高精度練習之加法

      #include #include #include using namespace std; const int maxn = 510; int a[maxn], b[maxn], c[maxn]; int main(){ string s1, s2; cin>>s1>>s2; a[0] = s1.size(); b[0] = s2.size(); for(int i = 1; i <= a[0]; i++)a[i] = s1[a[0]-i]-'0'; for(int i = 1; i <= b[0]; i++)b[i] = s2[b[0]-i]-'0'; c[0] = max(a[0], b[0])+1; for(int i = 1; i <= c[0]; i++){ c[i] += a[i]+b[i]; if(c[i]>=10){ c[i+1]++; c[i]%=10; } } while(c[0]>1 && c[c[0]]==0)c[0]--; for(int i = c[0]; i >= 1; i--)cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      高精度練習之乘法

      #include #include #include using namespace std; const int maxn = 510; int a[maxn], b[maxn], c[maxn]; int main(){ string s1, s2; cin>>s1>>s2; a[0] = s1.size(); b[0] = s2.size(); for(int i = 1; i <= a[0]; i++)a[i] = s1[a[0]-i]-'0'; for(int i = 1; i <= b[0]; i++)b[i] = s2[b[0]-i]-'0'; c[0] = a[0]+b[0]; for(int i = 1; i <= a[0]; i++){ for(int j =1; j <= b[0]; j++){ c[i+j-1] += a[i]*b[j]; if(c[i+j-1]>=10){ c[i+j] += c[i+j-1]/10; c[i+j-1] %= 10; } } } while(c[0]>1 && c[c[0]]==0)c[0]--; for(int i = c[0]; i >= 1; i--)cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      裝箱問題

      //數據太水,搜索就好 #include #include using namespace std; int n, m, a[110]; int search(int i, int r){ if(i == n)return r; if(r < a[i])return search(i+1, r); return min(search(i+1,r), search(i+1,r-a[i])); } int main(){ cin>>m>>n; for(int i = 0; i < n; i++)cin>>a[i]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      //f[i][j],表示在選第i個物品時, 大小為j的體積能否取到 #include using namespace std; const int maxn = 20010; int n, m, a[35], f[35][maxn]; int main(){ cin>>m>>n; for(int i = 1; i <= n; i++)cin>>a[i]; f[0][0] = 1; for(int i = 1; i <= n; i++) for(int j = 0; j <= m; j++) if(f[i-1][j]){ f[i][j] = f[i-1][j]; if(j+a[i]<=m)f[i][j+a[i]] = 1; } for(int i = m; i >= 0; i--) if(f[n][i]){ cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      //f[i]表示大小為i的體積能否取到 #include using namespace std; const int maxn = 20010; int n, m, a[maxn], f[maxn]; int main(){ cin>>m>>n; for(int i = 1; i <= n; i++)cin>>a[i]; f[0] = 1; for(int i = 1; i <= n; i++) for(int j = m; j >= 0; j--) if(f[j] && j+a[i]<=m) f[j+a[i]] = 1; for(int i = m; i >= 0; i--) if(f[i]){ cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      //01背包, f[i]表示體積為i時得到的最大價值 #include using namespace std; const int maxn = 20010; int n, m, w[35], v[35], f[maxn]; int main(){ cin>>m>>n; for(int i = 1; i <= n; i++){ cin>>w[i]; v[i] = w[i]; } for(int i = 1; i <= n; i++) for(int j = m; j >= w[i]; j--) f[j] = max(f[j],f[j-w[i]]+v[i]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      烏龜棋

      #include #include using namespace std; int n, m, a[350], num[5], f[50][50][50][50]; int main(){ cin>>n>>m; for(int i = 1; i <= n; i++)cin>>a[i]; for(int i = 1; i <= m; i++){ int x; cin>>x; num[x]++; } for(int i = 0; i <= num[1]; i++){ for(int j = 0; j <= num[2]; j++){ for(int k = 0; k <= num[3]; k++){ for(int l = 0; l <= num[4]; l++){ int t = 0; if(i)t = max(t, f[i-1][j][k][l]); if(j)t = max(t, f[i][j-1][k][l]); if(k)t = max(t, f[i][j][k-1][l]); if(l)t = max(t, f[i][j][k][l-1]); f[i][j][k][l] = t+a[i+j*2+k*3+l*4+1]; } } } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      攔截導彈

      //LDS的個數等于LIS的長度 #include #include using namespace std; int n, a[30], f[30], ans; int main(){ while(cin>>a[n])n++; for(int i = 0; i < n; i++)f[i] = 1; for(int i = 0; i < n; i++) for(int j = 0; j < i; j++) if(a[j]>=a[i])f[i] = max(f[i], f[j]+1); for(int i = 0; i < n; i++)ans = max(ans, f[i]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      最長嚴格上升子序列

      //f[i]:到i為止的LIS的長度。 //f[i]=max{1,f[j]+1|j #include using namespace std; int n, a[510], f[510], ans; int main(){ cin>>n; for(int i = 1; i <= n; i++)cin>>a[i]; for(int i = 1; i <= n; i++){ int t = 0; for(int j = 1; j < i; j++) if(a[j]

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      線段覆蓋 2

      //f[i]:到第i條線段為止能獲得的最大價值 //f[i]=max{s[i].c,f[j]+s[i].c|j #include using namespace std; const int maxn = 1010; struct seg{ int a, b, c; }s[maxn]; bool cmp(seg a, seg b){ return a.a>n; for(int i = 1; i <= n; i++) cin>>s[i].a>>s[i].b>>s[i].c; sort(s+1,s+n+1,cmp); for(int i = 1; i <= n; i++){ f[i] = s[i].c; for(int j = 1; j < i; j++) if(s[j].b<=s[i].a)f[i] = max(f[i], f[j]+s[i].c); ans = max(ans, f[i]); } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      石子歸并

      #include #include using namespace std; const int maxn = 1010, inf=0xffffff; int w[maxn], f[maxn][maxn]; int main(){ int n; cin>>n; for(int i = 1; i <= n; i++)cin>>w[i]; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) f[i][j] = i==j ? 0 : inf; for(int i = 1; i <= n; i++)w[i] += w[i-1]; //轉移順序長度從小到大覆蓋即可 for(int i = n; i >= 1; i--)//枚舉起點 for(int j = i; j <= n; j++)//枚舉終點 for(int k = i; k <= j; k++)//枚舉斷點 f[i][j] = min(f[i][j],f[i][k]+f[k+1][j]+w[j]-w[i-1]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      //解釋一下, DP題寫幾個版本主要看心情。。。 #include #include using namespace std; const int maxn = 1010, inf=0xffffff; int w[maxn], f[maxn][maxn]; int dp(int i, int j){ if(f[i][j] != inf)return f[i][j]; for(int k = i; k <= j; k++) f[i][j] = min(f[i][j], dp(i,k)+dp(k+1,j)+w[j]-w[i-1]); return f[i][j]; } int main(){ int n; cin>>n; for(int i = 1; i <= n; i++)cin>>w[i]; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) f[i][j] = i==j ? 0 : inf; for(int i = 1; i <= n; i++)w[i] += w[i-1]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      能量項鏈

      //環形DP, 復制一份, 拆環成鏈,然后做區間DP(即對每條鏈做一遍區間DP,取最大值。) //解釋一下, 注釋詳細度主要看心情。。。 #include #include using namespace std; const int maxn = 1010; int w[maxn], f[maxn][maxn]; int dp(int i, int j){ if(f[i][j])return f[i][j]; //注意邊界, [i~i,i+1~j] and [i~j-1,j~j]; for(int k = i; k <= j-1; k++) //通過k合并后, 兩顆珠子分別為[i,k],[k+1,j]其中計算能量時headi*taili*headj; f[i][j] = max(f[i][j], dp(i,k)+dp(k+1,j)+w[i]*w[k+1]*w[j+1]); return f[i][j]; } int main(){ int n; cin>>n; for(int i = 1; i <= n; i++){ cin>>w[i]; w[i+n]=w[i]; } dp(1, 2*n); int ans = 0; for(int i = 1; i <= n; i++)//掃描每條長度為n的鏈, 最大值為答案。 ans = max(ans, f[i][i+n-1]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      矩陣取數游戲

      //每行獨立區間DP, 貪心反例->某行像這樣,4 1 1 1 1 1 233 3 3 //2^80數據, 所以記得高精. #include #include #include #include #include using namespace std; typedef long long LL; typedef __int128 LLL; const int maxn = 110; int n, m, a[maxn]; LLL t[maxn], f[maxn][maxn], _max, ans; void print(LLL ans){ if(ans == 0)return ; else print(ans/10); putchar(ans%10+'0'); } int main(){ cin>>n>>m; t[0] = 1; for(int i = 1; i <= m; i++)t[i] = t[i-1]*2; while(n--){ for(int i = 1; i <= m; i++)cin>>a[i]; memset(f, 0, sizeof f); //f[i][j]:這行還剩下[i,j]時能得到的最高分 //轉移加上分別取了左邊的和右邊的數的時候的得分 //轉移順序,區間從大到小。 for(int i = 1; i <= m; i++) for(int j = m; j >= i; j--) f[i][j]=max(f[i-1][j]+t[m-(j-i+1)]*a[i-1], f[i][j+1]+t[m-(j-i+1)]*a[j+1]); //枚舉最后一個取的是哪個數,得到這一行的最高分 _max = 0; for(int i = 1; i <= m; i++)_max = max(_max, f[i][i]+t[m]*a[i]); ans += _max; } if(ans == 0)cout<<"0\n"; else print(ans); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      過河卒

      //填表法 #include using namespace std; int n, m, x, y, a[20][20], f[20][20]; int main(){ cin>>n>>m>>x>>y; x++;y++;n++;m++;//+1方便賦初始值 //9 points could'n be find a[x][y] = 1; a[x-1][y-2] = a[x-1][y+2] = a[x+1][y-2] = a[x+1][y+2] = 1; a[x-2][y-1] = a[x-2][y+1] = a[x+2][y-1] = a[x+2][y+1] = 1; f[0][1] = 1; //邊界 for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(!a[i][j])f[i][j] = f[i-1][j]+f[i][j-1]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      //刷表法 #include using namespace std; int n, m, x, y, a[20][20], f[20][20]; int main(){ cin>>n>>m>>x>>y; a[x][y] = 1; a[x-1][y-2] = a[x-1][y+2] = a[x+1][y-2] = a[x+1][y+2] = 1; a[x-2][y-1] = a[x-2][y+1] = a[x+2][y-1] = a[x+2][y+1] = 1; f[0][0] = 1;//初始值, 刷表時不會覆蓋所以可以直接放 for(int i = 0; i <= n; i++){ for(int j = 0; j <= m; j++){ if(!a[i+1][j])f[i+1][j] += f[i][j]; if(!a[i][j+1])f[i][j+1] += f[i][j]; } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      傳紙條

      //考慮題設,找到兩條不重復的路徑,所以從上到下直接DP,狀態四維(上往下,下往上分別DP,沒辦法考慮路徑重疊) //f[i][j][k][l]表示分別到(i,j),(k,l)時候的最大好心值 #include #include using namespace std; int n, m, a[55][55], f[55][55][55][55]; int main(){ cin>>n>>m; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin>>a[i][j]; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) for(int k = 1; k <= n; k++) for(int l = 1; l <= m; l++) if(!(i==k&&j==l) || (i==n&&j==m&&k==n&&l==m)) f[i][j][k][l] = max(max(f[i-1][j][k-1][l], f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1],f[i][j-1][k][l-1]))+a[i][j]+a[k][l]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      CodeVs天梯黃金Gold題解

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      騎士游歷

      //bugs:行列弄反(x,y是坐標軸...)+longlong #include using namespace std; typedef long long LL; LL n, m, x1, y1, x2, y2, f[55][55]; int main(){ cin>>n>>m>>x1>>y1>>x2>>y2; f[x1][y1] = 1; for(int i = x1+1; i <= x2; i++)//避免覆蓋掉x1,y1時候的1種方案 for(int j = 1; j <= n; j++)//因為日字,所以要全 f[i][j] = f[i-1][j-2]+f[i-1][j+2]+f[i-2][j-1]+f[i-2][j+1]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      //行列式反的,,, #include using namespace std; typedef long long LL; LL n, m, x1, y1, x2, y2, f[55][55]; int main(){ cin>>n>>m>>x1>>y1>>x2>>y2; f[y1][x1] = 1; //轉移的時候按照列每層去取(因為只能往右走) for(int i = x1; i <= x2; i++){//枚舉y for(int j = 1; j <= m; j++){//枚舉x //之前的狀態無法到達那么當前狀態也無法到達 if(!f[j][i])continue; //刷表狀態轉移 f[j+1][i+2] += f[j][i]; f[j-1][i+2] += f[j][i]; f[j+2][i+1] += f[j][i]; f[j-2][i+1] += f[j][i]; } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      數字三角形

      //f[i][j]:從(i,j)出發能獲得的最大值 _裸DFS #include #include using namespace std; int n, a[110][110], f[110][110]; int dfs(int i, int j){ if(f[i][j])return f[i][j]; if(i>n || j>n)return 0; return f[i][j] = max(dfs(i+1,j),dfs(i+1,j+1))+a[i][j]; } int main(){ cin>>n; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; j++) cin>>a[i][j]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      //f[i][j]:從(i,j)出發能獲得的最大值 _裸遞推 #include #include using namespace std; int n, a[110][110], f[110][110]; int main(){ cin>>n; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; j++) cin>>a[i][j]; for(int i = n; i >= 1; i--) for(int j = 1; j <= i; j++) f[i][j] = max(f[i+1][j], f[i+1][j+1])+a[i][j]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      //f[i][j]:從(1,1)到(i,j)能獲得的最大值 _裸遞推 #include #include using namespace std; int n, a[110][110], f[110][110]; int main(){ cin>>n; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; j++) cin>>a[i][j]; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; j++) f[i][j] = max(f[i-1][j], f[i-1][j-1])+a[i][j]; int ans = -0xffffff; for(int i = 1; i <= n; i++)ans = max(ans, f[n][i]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      //f[i][j]:從(i,j)出發能獲得的最大值 _滾動數組 #include #include using namespace std; int n, a[110][110], f[2][110]; int main(){ cin>>n; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; j++) cin>>a[i][j]; for(int i = n; i >= 1; i--) for(int j = 1; j <= i; j++) f[i%2][j] = max(f[(i+1)%2][j], f[(i+1)%2][j+1])+a[i][j]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      //f[i][j]:從(1,1)到(i,j)能獲得的最大值 _滾動數組2 #include #include using namespace std; int n, a, f[2][110]; int main(){ cin>>n; for(int i = 1; i <= n; i++){ for(int j = 1; j <= i; j++){ cin>>a; f[i%2][j] = max(f[(i-1)%2][j], f[(i-1)%2][j-1])+a; } } int ans = -0xffffff; for(int i = 1; i <= n; i++)ans = max(ans, f[n%2][i]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      乘積最大

      //f[i][j]:前i位數包含j個乘號時能獲得的最大值 //轉移,枚舉每個乘號的位置即可,O(n^3)可過。 #include #include #include using namespace std; typedef long long LL; int n, m; LL f[110][110]; string s; LL mid(int l, int r){ LL t = 0; for(int i = l; i <= r; i++) t = t*10+s[i-1]-'0';//第i位在s[i-1]; return t; } int main(){ cin>>n>>m>>s; for(int i = 1; i <= n; i++)f[i][0] = mid(1,i);//邊界條件,沒有乘號 for(int i = 1; i <= n; i++) //枚舉前i位數 for(int j = 1; j <= min(m,i-1); j++)//枚舉每個乘號(即子狀態) for(int k = j; k < i; k++)//枚舉該乘號的位置,乘號放后面(保證第j個乘號時, 前j-1個乘號的最優狀態已經算出來了) f[i][j] = max(f[i][j], f[k][j-1]*mid(k+1,i)); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      數的劃分

      //step1:把n個蘋果放到m個盤子里,不允許有空盤。等價于每個盤子放一個蘋果先允許有空盤 //step2:f[i][j]表示i個蘋果j個盤子的放法數目 //step3:轉移,j>i時,去掉空盤不影響結果; j<=i時,對盤子是否空著分類討論; #include using namespace std; int n, m, f[210][10]; int main(){ cin>>n>>m; n-=m;//每個盤子先放一個蘋果就不會有空盤了。。。 for(int i = 0; i <= n; i++)f[0][i]=f[i][1]=1; for(int i = 1; i <= n; i++) for(int j = 2; j <= m; j++) f[i][j] = j>i?f[i][i]:f[i][j-1]+f[i-j][j];//所有盤子有蘋果時每個盤子都去掉一個蘋果不影響結果 cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      //Step1:f[i][j]:將i這個整數劃分成j份且不重復的方法數 //Step2:因為劃分成的每一份至少為1,所以我們把它每份減去1 //Step3:將i這個數劃分成j份等價于將i-j這個數劃分成1份、2份、3份。。。j份的和 //Step4:f[i-1][j-1]=f[(i-1)-(j-1)][1]+...+f[(i-1)-(j-1)][j-1]; 代入化簡 #include #include using namespace std; int n, k, f[210][10]; int main(){ cin>>n>>k; f[0][0] = 1; for(int i = 1; i <= n; i++) for(int j = 1; j <= min(i,k); j++) f[i][j] = f[i-j][j]+f[i-1][j-1]; cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      統計單詞個數

      //just for test4 #include #include #include #include using namespace std; int n, m, x, d[210], f[210][50];//c[210][210]; string s, w[20]; void pre(){ memset(d, 0x3f, sizeof d); for(int i = 1; i <= s.size(); i++){//枚舉每個字母 for(int j = 1; j <= x; j++){//枚舉每個單詞 if(s.substr(i).find(w[j])==0){//如果存在i字母開頭的單詞 d[i] = min(d[i], i+(int)w[j].size()-1); } } } } int main(){ int T; cin>>T; while(T--){ //input cin>>n>>m; s = " "; for(int i = 1; i <= n; i++){ string t; cin>>t; s += t; } n *= 20; cin>>x; for(int i = 1; i <= x; i++)cin>>w[i]; //預處理1:得到c[i][j]為[i,j]中的最大單詞數 //預處理2:得到d[i]為字母i開頭的最短單詞的結束位置(小貪心,每個字母只能按照第一個字母取一次) pre(); //dp:f[i][j]為前i個字母劃分成j段能得到的最大單詞數 //轉移:f[i][j] = max{ f[k][j-1]+c[k+1][i] | k>=j&&k= j; k--){ //逆序覆蓋 if(d[k]<=i)w++; //w=[k,i] f[i][j] = max(f[i][j],f[k-1][j-1]+w); //f[i][j] = max(f[i][j], f[k][j-1]+w); //if(d[k]<=i)w++; //w=[k+1,i] } } } cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      四子連棋

      //思路:把空白當棋,交替黑白走。 //實現:BFS, 打表判斷是否成立 #include #include #include #include using namespace std; string s; struct node{ string ma; int step; char next; node(string x, int y, char ch):ma(x),step(y),next(ch){} }; queueq; int dz[] = {4,-4,1,-1}; char change(char ch){ if(ch == 'B')return 'W'; if(ch == 'W')return 'B'; } int check(string s){ //check diagonal 1 if(s[0]==s[5] && s[5]==s[10] && s[10]==s[15])return 1; //check diagonal 2 if(s[3]==s[6] && s[6]==s[9] && s[9]==s[12])return 1; //check row for(int i = 0; i < 4; i++){ int ok = 1, t = 4*i; for(int j = 0; j < 4; j++) if(s[t] != s[t+j])ok = 0; if(ok)return 1; } //check col for(int i = 0; i < 4; i++){ int ok = 1, t = i; for(int j = 0; j < 4; j++) if(s[t] != s[t+j*4])ok = 0; if(ok)return 1; } return 0; } int bfs(){ while(q.size()){ string t = q.front().ma; int st = q.front().step; char ch = q.front().next; q.pop(); //check if(check(t))return st; //find O int o1=-1, o2; for(int i = 0; i < 16; i++){ if(t[i]=='O'){ if(o1==-1)o1 = i; else o2 = i; } } //o1go for(int i = 0; i < 4; i++){ if(dz[i]==1 && o1%4==3)continue; if(dz[i]==-1 && o1%4==0)continue; int nz = o1+dz[i]; if(nz>=0 && nz<16 && t[nz]==ch){ string nt = t; swap(nt[o1],nt[nz]); q.push(node(nt,st+1,change(ch))); } } //o2go for(int i = 0; i < 4; i++){ if(dz[i]==1 && o2%4==3)continue; if(dz[i]==-1 && o2%4==0)continue; int nz = o2+dz[i]; if(nz>=0 && nz<16 && t[nz]==ch){ string nt = t; swap(nt[o2],nt[nz]); q.push(node(nt,st+1,change(ch))); } } } } int main(){ ios::sync_with_stdio(false); for(int i = 0; i < 4; i++){ string t; cin>>t; s += t; } if(check(s)){ cout<<"0"; return 0;} int ans = 0xffffff; q.push(node(s,0,'W')); ans = min(ans, bfs()); while(q.size())q.pop(); q.push(node(s,0,'B')); ans = min(ans, bfs()); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      逃跑的拉爾夫

      #include #include #include//set判重防MLE using namespace std; const int dx[4] = {-1, 0, 1, 0}; const int dy[4] = {0, 1, 0, -1}; int r, c, c1, r1, n, go[1010]; char a[55][55]; struct node{ int x, y, step; node(int x, int y, int step):x(x),y(y),step(step){} }; queueq; sets; bool inside(int x, int y){ return (x=0 && y=0 && a[x][y]!='X'); } int togo(char ch){ if(ch == 'N')return 0; if(ch == 'E')return 1; if(ch == 'S')return 2; if(ch == 'W')return 3; } void bfs(){ q.push(node(r1, c1, 0)); while(q.size()){ node t = q.front(); q.pop(); if(t.step == n)a[t.x][t.y] = '*'; int tt=go[t.step], nx=t.x+dx[tt], ny=t.y+dy[tt]; while(inside(nx,ny)){ int ok = nx*1000000+ny*10000+t.step+1; if(!s.count(ok)){ q.push(node(nx,ny,t.step+1)); s.insert(ok); } nx += dx[tt], ny += dy[tt]; } } return ; } int main(){ scanf("%d%d", &r, &c); for(int i = 0; i < r; i++)scanf("%s", a[i]); for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) if(a[i][j] == '*'){ r1 = i; c1 = j; break;} a[r1][c1] = '.'; scanf("%d",&n); for(int i= 0; i < n; i++){ char t[10]; scanf("%s", t); go[i] = togo(t[0]); } bfs(); for(int i = 0; i < r; i++)printf("%s\n", a[i]); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      字串變換

      //思路就是對于每個狀態下的字符串,枚舉可以替換的部分替換作為下一個新的狀態。 #include #include #include #include using namespace std; int n = 1, flag; string a, b, ai[1010], bi[1010]; queueq; mapma;//map判重防MLE int main(){ cin>>a>>b; while(cin>>ai[n]>>bi[n])n++; q.push(a); ma[a] = 0; while(q.size()){ string t = q.front(); q.pop(); if(t == b){ flag = 1; break; } if(ma[t]>10)break; //如果沒有這層循環的話,就只能找到第一個子串,后面的會被忽略,如abaaaba abcdaba for(int j = 0; j < t.size(); j++){ string nt = t.substr(j); for(int i = 1; i < n; i++){ int tt = nt.find(ai[i]); if(tt == string::npos)continue; tt += j; //邊界條件調起來很麻煩,以及最后直接+j就好了 string ttt = t.substr(0,tt)+bi[i]+t.substr(tt+ai[i].size()); if(!ma.count(ttt)){ ma[ttt] = ma[t]+1; q.push(ttt); } } } } if(flag)cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      #include #include #include #include //set判重 #define maxn 1010 using namespace std; string ai[maxn],bi[maxn]; struct node{ string str; int st; node(string a, int b):str(a),st(b){} }; sets; int ans; int main(){ string a, b; cin>>a>>b; int n = 1; while(cin>>ai[n]>>bi[n])n++; queueq; q.push(node(a,0)); while(q.size()){ node t = q.front(); q.pop(); if(t.str == b){ ans = t.st; break;} if(t.st > 10){ ans = 20; break; } for(int j = 0; j < t.str.size(); j++){ string nt = t.str.substr(j); for(int i = 1; i < n; i++){ int tt = nt.find(ai[i]); if(tt==string::npos)continue; tt += j; string ttt = t.str.substr(0,tt)+bi[i]+t.str.substr(tt+ai[i].size()); if(!s.count(ttt)){ q.push(node(ttt,t.st+1)); s.insert(ttt); } } } } //如果<10就因為找不到出來也是不成立的, 即ans沒有被賦過值的話 if(ans == 20 || ans == 0)cout<<"NO ANSWER!\n"; else cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      單詞接龍

      //直接搜索就好啦,幾乎沒什么技巧,就是狀態建模會有點難想到(應該有多種) //包含的情況可以證明是不需要考慮的,因為包含后一定不會比不包含要來的長 #include #include #include using namespace std; const int maxn = 30; int n, ans, used[maxn]; string w[maxn]; //找到a的末尾與b的前端重復的子串并返回其長度 int find(string a, string b){ int mm = min(a.size(), b.size()); for(int i = 1; i <= mm; i++) if(a.substr(a.size()-i)==b.substr(0,i)) return i; return 0; } //深度優先搜索尋找解, 狀態:s為當前字符串 void dfs(string s){ ans = max(ans, (int)s.size()); for(int i = 1; i <= n; i++)if(used[i]<2){ int t = find(s, w[i]); if(t == s.size() && s!=w[0])continue;//包含關系 if(t){ used[i]++; dfs(s.substr(0,s.size()-t)+w[i]); used[i]--; } } } int main(){ cin>>n; for(int i = 1; i <= n; i++)cin>>w[i]; cin>>w[0]; dfs(w[0]); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      四色問題

      //嘗試填每個點每種顏色填過去就好啦 #include using namespace std; int n, e[10][10]; int c[10], ans; void dfs(int cur){ if(cur == n)ans++; else for(int i = 0; i < 4; i++){ c[cur] = i; bool ok = true; for(int j = 0; j < cur; j++)//判斷和前面的點有沒有沖突 if(e[j][cur] && c[j]==c[cur])//如果聯通且同色那就翻車 { ok = false; break; } if(ok){ dfs(cur+1); } } } int main(){ cin>>n; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) cin>>e[i][j]; dfs(0); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      全排列

      #include using namespace std; int n, c[20]; void dfs(int cur){ if(cur == n){ for(int i = 0; i < n; i++)cout<>n; dfs(0); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      N皇后問題

      //c[i]:第i行的皇后放在第幾列 #include using namespace std; int n, c[20], ans; void dfs(int cur){ if(cur > n)ans++; else for(int i = 1; i <= n; i++){ int ok = 1; for(int j = 1; j < cur; j++) if(c[j]==i || c[j]-j==i-cur || c[j]+j==i+cur) { ok = 0; break; } if(ok){ c[cur] = i; dfs(cur+1); } } } int main(){ cin>>n; dfs(1); cout<

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      AI 云硬盤 EVS

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:word里怎么打分數?
      下一篇:華為云服務器可能是性價比最高的學生服務器
      相關文章
      国产精品亚洲αv天堂无码| 亚洲视频在线播放| 亚洲国产精品久久久久婷婷软件 | 无码专区—VA亚洲V天堂| 亚洲精品视频专区| 2048亚洲精品国产| 亚洲 小说区 图片区 都市| 亚洲人成网站在线观看播放动漫| 亚洲人成人77777网站| 日日噜噜噜噜夜夜爽亚洲精品| 亚洲午夜精品久久久久久浪潮| 亚洲国产高清国产拍精品| 国产亚洲精品VA片在线播放| 亚洲另类激情综合偷自拍 | 77777亚洲午夜久久多人| 亚洲精品高清在线| 亚洲情侣偷拍精品| 亚洲精品456播放| 亚洲熟伦熟女新五十路熟妇| 亚洲日韩国产精品乱| 亚洲国产精品一区二区九九| 亚洲国产精品狼友中文久久久| www.亚洲精品.com| 久久亚洲高清综合| 国产精品亚洲αv天堂无码| 国产亚洲精品a在线无码| 亚洲av中文无码乱人伦在线咪咕 | 亚洲欧洲日产国产最新| 亚洲伊人久久大香线焦| 亚洲中文字幕无码一去台湾 | 亚洲精品成人片在线观看| 亚洲国产精品国产自在在线 | 伊伊人成亚洲综合人网7777| 国产成人亚洲综合无码精品| 亚洲AV永久纯肉无码精品动漫 | 亚洲美女视频一区| 精品久久久久久亚洲精品| 亚洲一线产品二线产品| 国产成人综合亚洲一区| 亚洲国产人成中文幕一级二级| 国产中文在线亚洲精品官网|