这么水的题目居然没有做完真是愧对党的培养。只好拿期末没时间刷题码力下降来安慰下自己。弱鸡还是要多努力啊~~希望下一下不要在题数上被碾了ORZ
题目链接:
A
http://acm.neu.edu.cn/hustoj/problem.php?id=1664
和15年沈阳站的最后一道神似,建图如出一辙,把每个集合增加一个点就可以了。
#include <bits/stdc++.h>
using namespace std;
#define maxn 1111111
#define maxm 5111111
#define INF 11111111111111111
int n, m, s, f, p;
struct node {
int u, v, next;
long long w;
}edge[maxm];
int head[maxn], cnt;
void add_edge (int u, int v, int w) { //cout << u << " " << v << endl;
edge[cnt].u = u, edge[cnt].v = v, edge[cnt].w = w, edge[cnt].next = head[u], head[u] = cnt++;
return ;
}
long long d1[maxn], d2[maxn];
bool vis[maxn];
int top, num[maxn];
bool spfa (int start, long long *d) {
memset (vis, 0, sizeof vis);
for (int i = 1; i <= n+m; i++) {
d[i] = INF;
}
vis[start] = 1;
d[start] = 0;
queue <int> q;
while (!q.empty ()) q.pop ();
q.push (start);
memset (num, 0, sizeof num);
num[start] = 1;
while (!q.empty ()) {
int u = q.front (); q.pop ();
vis[u] = 0;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (d[v]>d[u]+edge[i].w) {
d[v] = d[u]+edge[i].w;
if (!vis[v]) {
vis[v] = 1;
q.push (v);
if (++num[v] > n+m)
return 0;
}
}
}
}
return 1;
}
int main () {
//freopen ("in.txt", "r", stdin);
while (scanf ("%d%d%d%d%d", &n, &m, &s, &f, &p) == 5) {
memset (head, -1, sizeof head);
cnt = 0;
for (int i = 1; i <= m; i++) {
int x, u, v;
long long w;
scanf ("%lld%d", &w, &x);
for (int j = 1; j <= x; j++) {
scanf ("%d", &u);
add_edge (u, i+n, w);
add_edge (i+n, u, 0);
}
}
spfa (s, d1);
//for (int i = 1; i <= n; i++) cout << d1[i] << " "; cout << endl;
spfa (f, d2);
//for (int i = 1; i <= n; i++) cout << d2[i] << " "; cout << endl;
if (d1[f] == INF || d2[p] == INF)
printf ("Poor guy, you don’t have enough Money!\n");
else
printf ("%lld\n", d1[f]+d2[p]);
}
}
B
http://acm.neu.edu.cn/hustoj/problem.php?id=1665
大水题啊有木有,结果上来理解错题目了,怎么想都有27种情况吧,然后后来发现,尼玛一样的情况视为一种,也是啊同样的密码如果错掉了一次怎么可能再错第二次。被自己蠢哭了~于是乎string暴力
#include <bits/stdc++.h>
using namespace std;
int main () {
//freopen ("in.txt", "r", stdin);
string a[3][3];
string ans;
while (cin >> a[0][0]) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 0 && j == 0)
continue;
cin >> a[i][j];
}
}
cin >> ans;
string gg[111];
int cnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
string cur = a[0][i] + a[1][j] + a[2][k];
bool ok = 0;
for (int l = 0; l < cnt; l++) {
if (gg[l] == cur) {
ok = 1;
break;
}
}
if (!ok) {
gg[cnt++] = cur;
}
}
}
}
if (cnt <= 6) {
printf ("1/1\n");
continue;
}
int g = __gcd (6, cnt);
printf ("%d/%d\n", 6/g, cnt/g);
}
return 0;
}
C
http://acm.neu.edu.cn/hustoj/problem.php?id=1666
都是泪啊~刚开始用map写超时了(最后证明超时的原因是因为我第一个a[0]的输入用了cin),然后就一直不敢map了,然后一直在用二分离散化什么的瞎搞,搞对了自己出的数据死活过不去。然后学长告诉我他就是map写的,最后还剩10多分钟的时候重写map发现WA,最后结束了发现是自己把a数组开成long long但是a[0]输入用了%d。又一次被自己蠢哭~
#include <bits/stdc++.h>
using namespace std;
#define maxn 8111111
long long a[33];
long long sum[111111];
long long num[111111];
char s[111111];
map <long long, long long> gg;
int main () {
//freopen ("in.txt", "r", stdin);
while (scanf ("%lld", &a[0]) == 1) {
for (int i = 1; i < 26; i++) {
scanf ("%lld", &a[i]);
}
scanf ("%s", s);
long long ans = 0;
int n = strlen (s);
for (int i = 0; i < n; i++) {
num[i] = a[s[i]-'a'];
sum[i] = (i == 0 ? 0 : sum[i-1]) + num[i];
}
for (int i = 0; i < 26; i++) {
gg.clear ();
for (int j = 0; j < n; j++) {
if (s[j] == 'a' + i) {
if (gg.count (sum[j]-a[i])) {
ans += gg[sum[j]-a[i]];
}
if (gg.count (sum[j])) {
gg[sum[j]]++;
}
else gg[sum[j]] = 1;
}
}
}
printf ("%lld\n", ans);
}
return 0;
}
D
http://acm.neu.edu.cn/hustoj/problem.php?id=1667
题意很坑,按照我自己的ac代码题意应该是这样的:求最长的合法子序列(不必连续),答案就是这个合法子序列的匹配数也就是长度除以2.
裸地区间DP如果头尾匹配就匹配,然后在枚举中间断点更新DP值。
#include <bits/stdc++.h>
using namespace std;
#define maxn 111
int dp[maxn][maxn];
char a[maxn];
bool ok (char a, char b) {
if (a == '#' && b == '*')
return 1;
else if (a== '%' && b == '&')
return 1;
return 0;
}
int main () {
//freopen ("in.txt", "r", stdin);
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%s", a);
memset (dp, 0, sizeof dp);
int n = strlen (a); //cout << n << endl;
for (int l = 1; l < n; l++) {
for (int i = 0; i+l < n; i++) {
int j = l+i;
if (ok (a[i], a[j])) {
dp[i][j] = max (dp[i+1][j-1]+1, dp[i][j]);
}
//dp[i][j] = max (dp[i][j], max (dp[i+1][j], dp[i][j-1]));
for (int k = i+1; k <= j; k++) {
dp[i][j] = max (dp[i][j], dp[i][k-1]+dp[k][j]);
}
}
}
printf ("%d\n", dp[0][n-1]);
}
return 0;
}
E
http://acm.neu.edu.cn/hustoj/problem.php?id=1668
判断点在三角形里面还是外面还是边上。
这道题又一次充分了证明了自己有多蠢,有理有据令人信服。
第一次写成了ok[0]==ok[1]==ok[2]T.T,第二次发现有一个输出少打了一个点。。。
这么简单的题目其实什么姿势都能过,我是判断了三次点在线段上和点在直线左侧的to_left_test测试。
#include <bits/stdc++.h>
using namespace std;
bool ok[3];
typedef unsigned long long ll;
#define maxn 111111
#define pi acos (-1)
#define rotate Rotate
const double eps = 1e-8;
int dcmp (double x) {
if (fabs (x) < eps)
return 0;
else return x < 0 ? -1 : 1;
}
struct point {
double x, y;
point (double _x = 0, double _y = 0) : x(_x), y(_y) {}
point operator - (point a) const {
return point (x-a.x, y-a.y);
}
point operator + (point a) const {
return point (x+a.x, y+a.y);
}
bool operator < (const point &a) const {
return x < a.x || (x == a.x && y < a.y);
}
bool operator == (const point &a) const {
return dcmp (x-a.x) == 0 && dcmp (y-a.y) == 0;
}
}a[3], b;
point operator * (point a, double p) {
return point (a.x*p, a.y*p);
}
double cross (point a, point b) {
return a.x*b.y-a.y*b.x;
}
double dot (point a, point b) {
return a.x*b.x + a.y*b.y;
}
bool OnSegment (point p, point a1, point a2) {
return dcmp (cross (a1-p, a2-p) == 0) && dcmp (dot (a1-p, a2-p) <= 0);
}
bool ToLeftTest (point a, point p1, point p2) {
return (cross (a-p1, p2-p1) >= 0);
}
int main () {
//freopen ("in.txt", "r", stdin);
int t;
cin >> t;
while (t--) {
cin >> b.x >> b.y;
for (int i = 0; i < 3; i++) {
cin >> a[i].x >> a[i].y;
}
for (int i = 0; i < 3; i++) {
if (OnSegment (b, a[i], a[(i+1)%3])) {
cout << "Not quite clear..." << endl;
goto out;
}
}
for (int i = 0; i < 3; i++) {
ok[i] = ToLeftTest (b, a[i], a[(i+1)%3]);
}
//cout << ok[0] << " " << ok[1] << " " << ok[2] << endl;
if (ok[0] == ok[1] && ok[1] == ok[2]) {
cout << "Here it is!" << endl;
}
else cout << "Can't find it." << endl;
out: ;
}
return 0;
}
F
http://acm.neu.edu.cn/hustoj/problem.php?id=1669
小模拟,2048火的时候玩烂了都,毫无问题~多玩玩游戏还是好的哈哈
#include <bits/stdc++.h>
using namespace std;
#define maxn 11
int mp[maxn][maxn];
int main () {
//freopen ("in.txt", "r", stdin);
int t;
scanf ("%d", &t);
while (t--) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
scanf ("%d", &mp[i][j]);
}
}
int q;
scanf ("%d", &q);
while (q--) {
int op;
scanf ("%d", &op); //cout << ".." << endl;
if (op == 1) {
for (int i = 0; i < 4; i++) {//列数
for (int k = 1; k < 4; k++) {//行数
int j = k;
while (j > 0) {
if (mp[j-1][i] == 0) { //移动
swap (mp[j-1][i], mp[j][i]);
}
else if (mp[j-1][i] == mp[j][i]) { //合并
mp[j-1][i] *= 2;
mp[j][i] = 0;
break;
}
else break;
j--;
}
}
}
}
else if (op == 2) {
for (int i = 0; i < 4; i++) {
for (int k = 2; k >= 0; k--) {
int j = k;
while (j < 3) {
if (mp[j+1][i] == 0) {
swap (mp[j+1][i], mp[j][i]);
}
else if (mp[j+1][i] == mp[j][i]) {
mp[j+1][i] *= 2;
mp[j][i] = 0;
break;
}
else
break;
j++;
}
}
}
}
else if (op ==3) {
for (int i = 0; i < 4; i++) {
for (int k = 1; k < 4; k++) {
int j = k;
while (j > 0) {
if (mp[i][j-1] == 0) {
swap (mp[i][j-1], mp[i][j]);
}
else if (mp[i][j-1] == mp[i][j]) {
mp[i][j-1] *= 2;
mp[i][j] = 0;
break;
}
else break;
j--;
}
}
}
}
else if (op == 4) {
for (int i = 0; i < 4; i++) {
for (int k = 2; k >= 0; k--) {
int j = k;
while (j < 3) {
if (mp[i][j+1] == 0) {
swap (mp[i][j+1], mp[i][j]);
}
else if (mp[i][j+1] == mp[i][j]) {
mp[i][j+1] *= 2;
mp[i][j] = 0;
break;
}
else break;
j++;
}
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
printf ("%5d", mp[i][j]);
}
printf ("\n");
}
printf ("\n");
}
}
return 0;
}