A长方体
链接:https://www.nowcoder.com/acm/contest/109/A
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给出共享长方体一个顶点的三个面的面积,求它十二条边的边长和。
输入描述:
一行三个整数a, b, c表示面积(1 <= a, b, c <= 10000)。
输出描述:
一行一个整数表示边长和。
示例1
输入
1 1 1
输出
12
示例2
输入
4 6 6
输出
28
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = (int) 10000 + 11;
const int M = (int) 1e6 + 11;
const int mod = (int) 1e9 + 7;
const int INF = 0x3f3f3f3f;
int main(){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
if(i * j != a) continue;
for(int k = 1; k <= N; k++){
if(i * k == b && j * k == c){
printf("%d\n",(i + j + k) * 4);
return 0;
}
}
}
}
return 0;
}
E 求长度
链接:https://www.nowcoder.com/acm/contest/109/E
来源:牛客网
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一幅n个点m条边的图和S个一定要经过的点,问从0号点出发,经过这S个点再回到0号点的最短路径长度是多少。
输入描述:
第一行一个整数T(T <= 2)表示数据组数。
对于每组数据,第一行两个整数n,m表示点数和边数(1 <= n, m <= 100,000)。
接下来m行,每行三个整数x, y, z(0 < x, y < n, 0 <= z <= 1000)表示xy之间有一条长度为c的双向边;
接下来一个整数S。(S<=10)
接下来S行每行一个整数表示一定要经过的点。
数据保证有解。
输出描述:
T行,每行一个整数表示答案。
示例1
输入
1
4 6
0 1 1
1 2 1
2 3 1
3 0 1
0 2 5
1 3 5
3
1
2
3
输出
4
分析: 一开始看 感觉很像 优先队列的BFS + 状态压缩 (感觉和之前做的很像),但是却无限WA, 好吧, 通过这次,我明白了, 状态压缩 不能够加 优先队列的BFS,如果每次移动都是相同距离,那么就可以用了。
就比如下面这个数据 就过不了。
1
4 6
0 1 1
1 2 1
2 3 1
3 0 1
0 2 5
1 3 5
2
2
3
出问题的点: 到达 2这个点的时候,一定是最短的,而且状态正好是满的(走完了所有关键点),但是它却有一条边直接走向了0,但是最短的路径却不是这个。
状压 + BFS的错误代码
#include <bits/stdc++.h>
using namespace std;
const int N = (int) 1e5 + 11;
const int M = (int) 1e6 + 11;
struct Node{
int id, step, state;
Node(){}
Node(int _id, int _step, int _state){
id = _id; step = _step; state = _state;
}
friend bool operator < (Node a, Node b){
return a.step > b.step;
}
};
struct Edge{
int from, to, val, next;
Edge(){}
Edge (int _from, int _to, int _val, int _next){
from = _from; to = _to; val = _val; next = _next;
}
}edge[N * 2 + 1];
int head[N + 1], top; int n, m, ss;
void init(){
memset(head, -1, sizeof(int) * (n + 1));
top = 0;
}
void Addedge(int a, int b, int c){
edge[top] = Edge(a, b, c, head[a]);
head[a] = top++;
edge[top] = Edge(b, a, c, head[b]);
head[b] = top++;
}
void getmap(){
int a, b, c;
while(m--){
scanf("%d%d%d", &a, &b, &c);
Addedge(a, b, c);
}
}
bool vis[N + 1][(1 << 11)];
map <int, int> ID; int full;
int BFS(){
memset(vis, false, sizeof(vis));
priority_queue <Node> que;
que.push(Node(0, 0, 0)); //vis[0][0] = 1;
while(!que.empty()){
Node now = que.top(); que.pop();
// printf("@@@ %d %d %d \n", now.id, now.step, now.state);
if(now.id == 0 && now.state == full){
return now.step;
}
for(int i = head[now.id]; i != -1; i = edge[i].next){
Edge e = edge[i];
if(vis[e.to][now.state] == 1) continue;
vis[e.to][now.state] = 1;
int sta = now.state;
if(ID[e.to] != 0) sta = now.state | (1 << (ID[e.to] - 1));
que.push(Node(e.to, now.step + e.val, sta));
}
}
return -1;
}
int main(){
int T; scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
init();
getmap();
scanf("%d", &ss);
ID.clear(); full = 0;
for(int i = 0; i < ss; i++) {
int tmp; scanf("%d", &tmp);
ID[tmp] = i + 1;
full |= (1 << i);
}
// printf("%d \n", full);
printf("%d\n", BFS());
}
return 0;
}
正解: 思路写在了代码中:
代码
#include <bits/stdc++.h>
using namespace std;
const int N = (int) 1e5 + 11;
const int M = (int) 1e6 + 11;
struct Edge{
int from, to, val, next;
Edge(){}
Edge (int _from, int _to, int _val, int _next){
from = _from; to = _to; val = _val; next = _next;
}
}edge[N * 2 + 1];
int head[N + 1], top; int n, m, ss;
void init(){
memset(head, -1, sizeof(int) * (n + 1));
top = 0;
}
void Addedge(int a, int b, int c){
edge[top] = Edge(a, b, c, head[a]);
head[a] = top++;
}
bool vis[N + 1]; int Dis[N + 1];
int SPFA(int s,int t){
memset(Dis, 0x3f, sizeof(int) * (n + 1));
memset(vis, false, sizeof(bool) * (n + 1));
vis[s] = true; Dis[s] = 0;
queue<int> que; que.push(s);
while(!que.empty()){
int now = que.front(); que.pop(); vis[now] = false;
for(int i = head[now]; i != -1; i = edge[i].next){
Edge e = edge[i];
if(Dis[e.to] > Dis[now] + e.val) {
Dis[e.to] = Dis[now] + e.val;
if(!vis[e.to]){
que.push(e.to);
vis[e.to] = true;
}
}
}
}
return Dis[t];
}
int dis[20][20], p[20];
int Solve(){
int a, b, c;
while(m--){
scanf("%d%d%d", &a, &b, &c);
Addedge(a, b, c);
Addedge(b, a, c);
}
int ss; scanf("%d", &ss);
p[0] = 0;
for(int i = 1; i <= ss; i++ ) scanf("%d", &p[i]);
memset(dis, 0x3f, sizeof(dis));
for(int i = 0; i <= ss; i++) { // 得到任意两个关键点之间的最短路
for(int j = 0; j <= ss; j++){
dis[i][j] = SPFA(p[i], p[j]);
}
}
Dis[0] = 0;
for(int i = 1; i <= ss; i++) Dis[i] = i;
int ans = 0x3f3f3f3f;
do{ // 遍历所有 可以访问到所有关键点的 顺序
int sum = dis[Dis[ss]][Dis[0]];
for(int i = 1; i <= ss; i++)
sum += dis[Dis[i-1]][Dis[i]];
if(sum < ans) ans = sum;
}while(next_permutation(Dis + 1, Dis + ss + 1)) ;
return ans;
}
int main(){
int T; scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
init();
printf("%d\n", Solve());
}
return 0;
}
/*
200
4 6
0 1 1
1 2 1
2 3 1
3 0 1
0 2 5
1 3 5
1
1
*/