链接:https://ac.nowcoder.com/acm/contest/4462
来源:nowcoder
思路:类似于树的直径问题,如果权值都为正值我们可以直接两次 b f s bfs bfs 即可,现在权值有赋值,我们可以用 d p dp dp 来解决, d p [ i ] dp[i] dp[i] 表示从 i i i 结点出发向下走的最长子链的长度(我们以 1 1 1 号结点作为根结点)。直接 d f s dfs dfs 更新 d p dp dp 的值即可。
#include
using namespace std;
#define pb push_back
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int maxn=1e5+10;
ll dp[maxn],ans=-inf;
int w[maxn];
vector<int>G[maxn];
void dfs(int u,int fa){
dp[u]=w[u];
for(auto v:G[u]){
if(v==fa) continue;
dfs(v,u);
ans=max(ans,dp[u]+dp[v]);
dp[u]=max(dp[u],dp[v]+w[u]);
}
ans=max(ans,dp[u]);
}
int main(){
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++){
int u,v; scanf("%d%d",&u,&v);
G[u].pb(v); G[v].pb(u);
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}
思路:我们可以注意到纸片的数量比较少,所以我们直接搜索出每一种情况作出判断即可。
#include
using namespace std;
const int maxn=15;
int x[maxn],y[maxn];
bool vis[maxn];
int n,ans=INT_MAX;
int dis(int i,int j){
return abs(x[i]-x[j])+abs(y[i]-y[j]);
}
void dfs(int now,int Min,int cnt){
if(cnt==n){
ans=min(ans,Min+dis(now,0));
return ;
}
for(int i=1;i<=n;i++){
if(vis[i]) continue;
vis[i]=true;
dfs(i,Min+dis(now,i),cnt+1);
vis[i]=false;
}
}
int main(){
int T; scanf("%d",&T);
while(T--){
int r,c; scanf("%d%d",&r,&c);
scanf("%d%d",&x[0],&y[0]);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
dfs(0,0,0);
printf("The shortest path has length %d\n",ans);
}
return 0;
}
思路:签到题,直接涂前 a a a 行和前 b b b 列,然后计算剩下没有涂色的即可。
#include
using namespace std;
int main(){
long long n,m,a,b;
while(cin>>n>>m>>a>>b){
cout<<n*m-(a*m+b*n-a*b)<<endl;
}
return 0;
}
思路:在 n n n 后面加 2 d 2d 2d 个 0 0 0 即可,最近遇到大数比较多,没有思索直接就高精度乘单精度来计算了。
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int ans[maxn];
int main(){
int n,d;
while(~scanf("%d%d",&n,&d)){
int len=0;
ans[0]=1; len=1;
for(int i=0;i<len;i++) ans[i]*=n;
for(int i=0;i<len;i++){
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
while(ans[len]){
ans[len+1]+=ans[len]/10;
ans[len]%=10;
len++;
}
for(int q=1;q<=d;q++){
for(int i=0;i<len;i++) ans[i]*=100;
for(int i=0;i<len;i++){
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
while(ans[len]){
ans[len+1]+=ans[len]/10;
ans[len]%=10;
len++;
}
}
for(int i=len-1;i>=0;i--) printf("%d",ans[i]);
puts("");
for(int i=0;i<len;i++) ans[i]=0;
}
return 0;
}
思路:由于数据范围比较小,直接枚举算出在每一个点的值,最后找到最小值就行了。
#include
using namespace std;
#define pb push_back
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f;
const int maxn=1e2+10;
int a[maxn][maxn];
struct Node{
int x,y;
Node(){}
Node(int x,int y):x(x),y(y){}
};
ll dis(Node node1,Node node2){
return abs(node1.x-node2.x)+abs(node1.y-node2.y);
}
int main(){
int T; scanf("%d",&T);
while(T--){
ll ans=inf;
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
Node node=Node(i,j);
ll res=0;
for(int x=1;x<=m;x++){
for(int y=1;y<=n;y++){
res+=dis(node,Node(x,y))*a[x][y];
}
}
ans=min(ans,res);
}
}
printf("%lld\n",ans);
}
return 0;
}
思路:分别用 v e t o r vetor vetor 记录某个区间放入了什么数据, l [ i ] l[i] l[i] r [ i ] r[i] r[i] 记录区间的头和尾放入的货物 i d id id。 v i s vis vis 用来表示编号为 i i i 的物品的数量。遍历 [ 1 , n ] [1,n] [1,n] 用差分的方法来一次计算每个仓库放了多少种货物。
#include
using namespace std;
#define pb push_back
const int maxn=1e5+10;
vector<int>l[maxn],r[maxn];
map<int,int>vis;
int main(){
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int l1,r1,d; scanf("%d%d%d",&l1,&r1,&d);
l[l1].pb(d); r[r1+1].pb(d);
}
int ans=-1,inx=-1,cnt=0;
for(int i=1;i<=n;i++){
for(auto j:l[i]){
if(!vis[j]) cnt++;//当前货物没有数量为 0,货物需要加一种
vis[j]++;//该仓库当前货物数量
}
for(auto j:r[i]){
vis[j]--;//该仓库当前货物数量
if(!vis[j]) cnt--;//当前货物没有了
}
//cout<
if(ans<cnt){
ans=cnt;
inx=i;
}
}
//cout<
printf("%d\n",inx);
return 0;
}
思路:此题换成了保证没有前导 0 0 0 的情况,所以直接分离出 A A A 和 B B B进行大数加法即可。多组数据,注意数组的清空问题。
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
char str[maxn],a[maxn],b[maxn];
int c[maxn],d[maxn],ans[2*maxn];
void cal(){
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(ans,0,sizeof(ans));
int lena=strlen(a),lenb=strlen(b);
for(int i=0;i<lena;i++) c[i]=a[lena-i-1]-'0';
for(int i=0;i<lenb;i++) d[i]=b[lenb-i-1]-'0';
int len=max(lena,lenb);
for(int i=0;i<len;i++){
ans[i]+=c[i]+d[i];
if(ans[i]>9){
ans[i]-=10;
ans[i+1]++;
}
}
len=ans[len]?len+1:len;
for(int i=len-1;i>=0;i--) printf("%d",ans[i]);
puts("");
}
int main(){
int T; scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%s",str);
int n=strlen(str),cnt1=0,cnt2=0;
int inx=-1;
for(int i=0;i<n;i++){
if(str[i]<='9'&&str[i]>='0') a[cnt1++]=str[i];
if(str[i]=='+') { inx=i;break; }
}
if(inx==-1||inx==n-1||inx==0){
puts("skipped");
continue;
}
bool flag=true;
for(int i=inx+1;i<n;i++){
if(str[i]<='9'&&str[i]>='0') b[cnt2++]=str[i];
else {
flag=false;
break;
}
}
//cout<
if(flag){
//puts(a); puts(b);
cal();
}else{
puts("skipped");
}
}
return 0;
}