题号:1052
参考题解:
https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P1052
作者: CoolTeam 更新时间: 2015-08-11 18:26
作者: shutdown 更新时间: 2013-07-30 20:20
作者: VengefulSpirit 更新时间: 2013-06-25 11:17
作者: sb123 更新时间: 2017-08-07 17:58
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 | #include<iostream> #include<algorithm> #include<string> #include<utility> #include<queue> #include<cstdlib> #include<cstring> #include<map> using namespace std; int f[20005]; int Mk[105],M[105]; //ifstream cin("in.txt"); //ofstream cout("out.txt"); int main(){ ios::sync_with_stdio(false); int l, s, t, m,ans=0; cin >> l >> s >> t >> m; for (int i = 1; i <= m; i++){ cin >> Mk[i];//存入M的临时数组 } if (s == t){//当s==t时是特殊情况,只需判断为s/t倍数的点有无石子即可 ;参考CoolTeam。为啥用动态规划过不了,我也不知道 for (int i = 1; i <= m; i++){ if (Mk[i] % s == 0)ans++; } cout << ans; return 0; } //否则需要使用动态规划 memset(f, 0x7f, sizeof(f)); f[0] = 0; sort(Mk + 1, Mk + m + 1); //先给临时数组排个序 for (int i = 1; i <= m; i++){ if (Mk[i] - Mk[i - 1] >= 100)M[i] = M[i - 1] + 100; //如果两相邻石子之间距离大于100,就将他们之间的距离缩小到100 ;参考shutdown的结论,VengefulSpirit的证明过程 else M[i] = M[i - 1] + Mk[i] - Mk[i - 1]; } int M_cnt = 1; for (int i = 1; i <= M[m]+t; i++){ //比较容易的动态规划 ;参考sb123的动规转移方程 for (int j = i-s; j >= max(i - t,0); j--){ f[i] = min(f[j], f[i]); } if (M[M_cnt] == i){ f[i]++; M_cnt++; } } ans = 10000; for (int i = M[m] + t-1; i >= M[m]; i--)ans = min(ans, f[i]); //遍历从最后一个石子到最后一个石子+t-1的最短距离 cout << ans; } |
20180805更新,表示缩点/离散化恶心死了,写了半天60,迫不得已看题解了。、
参考题解:https://www.luogu.org/blog/GXu/solution-p1052
https://peerless.blog.luogu.org/guo-he-xie-ti-bao-gao
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 | #include<iostream> #include<string> #include<algorithm> #include<functional> #define ll long long #define pii pair<int,int> #define PINF 0x7fffffff #define NINF 0x80000000 using namespace std; int l; int s, t, m; int pos[105]; int d[105]; bool stone[400000]; int f[400000]; int main() { cin >> l >> s >> t >> m; for (int i = 1; i <= m; i++)cin >> pos[i]; sort(pos + 1, pos + m + 1); for (int i = 1; i <= m; i++)d[i] = (pos[i] - pos[i - 1]) % 2520; for (int i = 1; i <= m; i++) { pos[i] = pos[i - 1] + d[i]; stone[pos[i]] = true; } l = pos[m]; for (int i = 1; i <= l + t; i++)f[i] = m; for (int i = 1; i <= l + t; i++) { for (int j = s; j <= t; j++) { if (i >= j)f[i] = min(f[i], f[i - j]); f[i] += stone[i]; } } int ans = m; for (int i = l; i < l + t; i++)ans = min(ans, f[i]); cout << ans; } |